wined3d: Handle CTXUSAGE_BLIT with offscreen targets and FBO ORM.
[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->frag_pipe->free_private(iface);
2238     This->shader_backend->shader_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->frag_pipe->free_private(iface);
2328     This->shader_backend->shader_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     /* Only set the values up once, as they are not changing */
5030     if (Flags & WINED3DCLEAR_STENCIL) {
5031         glClearStencil(Stencil);
5032         checkGLcall("glClearStencil");
5033         glMask = glMask | GL_STENCIL_BUFFER_BIT;
5034         glStencilMask(0xFFFFFFFF);
5035     }
5036
5037     if (Flags & WINED3DCLEAR_ZBUFFER) {
5038         DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
5039         glDepthMask(GL_TRUE);
5040         glClearDepth(Z);
5041         checkGLcall("glClearDepth");
5042         glMask = glMask | GL_DEPTH_BUFFER_BIT;
5043         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
5044
5045         if (vp->X != 0 || vp->Y != 0 ||
5046                 vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) {
5047             surface_load_ds_location(This->stencilBufferTarget, location);
5048         }
5049         else if (This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
5050                 This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
5051                 This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width ||
5052                 This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) {
5053             surface_load_ds_location(This->stencilBufferTarget, location);
5054         }
5055         else if (Count > 0 && pRects && (
5056                 pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
5057                 pRects[0].x2 < depth_stencil->currentDesc.Width ||
5058                 pRects[0].y2 < depth_stencil->currentDesc.Height)) {
5059             surface_load_ds_location(This->stencilBufferTarget, location);
5060         }
5061     }
5062
5063     if (Flags & WINED3DCLEAR_TARGET) {
5064         TRACE("Clearing screen with glClear to color %x\n", Color);
5065         glClearColor(D3DCOLOR_R(Color),
5066                      D3DCOLOR_G(Color),
5067                      D3DCOLOR_B(Color),
5068                      D3DCOLOR_A(Color));
5069         checkGLcall("glClearColor");
5070
5071         /* Clear ALL colors! */
5072         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5073         glMask = glMask | GL_COLOR_BUFFER_BIT;
5074     }
5075
5076     vp_rect.left = vp->X;
5077     vp_rect.top = vp->Y;
5078     vp_rect.right = vp->X + vp->Width;
5079     vp_rect.bottom = vp->Y + vp->Height;
5080     if (!(Count > 0 && pRects)) {
5081         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5082             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
5083         }
5084         if(This->render_offscreen) {
5085             glScissor(vp_rect.left, vp_rect.top,
5086                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
5087         } else {
5088             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
5089                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
5090         }
5091         checkGLcall("glScissor");
5092         glClear(glMask);
5093         checkGLcall("glClear");
5094     } else {
5095         /* Now process each rect in turn */
5096         for (i = 0; i < Count; i++) {
5097             /* Note gl uses lower left, width/height */
5098             IntersectRect((RECT *) &curRect, &vp_rect, (RECT *) &pRects[i]);
5099             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5100                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
5101             }
5102             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
5103                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
5104                   curRect.x1, (target->currentDesc.Height - curRect.y2),
5105                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5106
5107             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
5108              * The rectangle is not cleared, no error is returned, but further rectanlges are
5109              * still cleared if they are valid
5110              */
5111             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
5112                 TRACE("Rectangle with negative dimensions, ignoring\n");
5113                 continue;
5114             }
5115
5116             if(This->render_offscreen) {
5117                 glScissor(curRect.x1, curRect.y1,
5118                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5119             } else {
5120                 glScissor(curRect.x1, drawable_height - curRect.y2,
5121                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5122             }
5123             checkGLcall("glScissor");
5124
5125             glClear(glMask);
5126             checkGLcall("glClear");
5127         }
5128     }
5129
5130     /* Restore the old values (why..?) */
5131     if (Flags & WINED3DCLEAR_STENCIL) {
5132         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5133     }
5134     if (Flags & WINED3DCLEAR_TARGET) {
5135         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
5136         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5137                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5138                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
5139                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5140
5141         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
5142          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
5143          */
5144         IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE);
5145         /* TODO: Move the fbo logic into ModifyLocation() */
5146         if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5147             target->Flags |= SFLAG_INTEXTURE;
5148         }
5149     }
5150     if (Flags & WINED3DCLEAR_ZBUFFER) {
5151         /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
5152         DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
5153         surface_modify_ds_location(This->stencilBufferTarget, location);
5154     }
5155
5156     LEAVE_GL();
5157
5158     return WINED3D_OK;
5159 }
5160
5161 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
5162                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
5163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5164     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
5165
5166     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
5167           Count, pRects, Flags, Color, Z, Stencil);
5168
5169     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
5170         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
5171         /* TODO: What about depth stencil buffers without stencil bits? */
5172         return WINED3DERR_INVALIDCALL;
5173     }
5174
5175     return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil);
5176 }
5177
5178 /*****
5179  * Drawing functions
5180  *****/
5181 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5182                                                 UINT PrimitiveCount) {
5183
5184     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5185
5186     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5187                                debug_d3dprimitivetype(PrimitiveType),
5188                                StartVertex, PrimitiveCount);
5189
5190     if(!This->stateBlock->vertexDecl) {
5191         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5192         return WINED3DERR_INVALIDCALL;
5193     }
5194
5195     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
5196     if(This->stateBlock->streamIsUP) {
5197         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5198         This->stateBlock->streamIsUP = FALSE;
5199     }
5200
5201     if(This->stateBlock->loadBaseVertexIndex != 0) {
5202         This->stateBlock->loadBaseVertexIndex = 0;
5203         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5204     }
5205     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
5206     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5207                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5208     return WINED3D_OK;
5209 }
5210
5211 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5212 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5213                                                            WINED3DPRIMITIVETYPE PrimitiveType,
5214                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
5215
5216     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5217     UINT                 idxStride = 2;
5218     IWineD3DIndexBuffer *pIB;
5219     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
5220     GLuint vbo;
5221
5222     pIB = This->stateBlock->pIndexData;
5223     if (!pIB) {
5224         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5225          * without an index buffer set. (The first time at least...)
5226          * D3D8 simply dies, but I doubt it can do much harm to return
5227          * D3DERR_INVALIDCALL there as well. */
5228         ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
5229         return WINED3DERR_INVALIDCALL;
5230     }
5231
5232     if(!This->stateBlock->vertexDecl) {
5233         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5234         return WINED3DERR_INVALIDCALL;
5235     }
5236
5237     if(This->stateBlock->streamIsUP) {
5238         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5239         This->stateBlock->streamIsUP = FALSE;
5240     }
5241     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
5242
5243     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
5244           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5245           minIndex, NumVertices, startIndex, primCount);
5246
5247     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5248     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5249         idxStride = 2;
5250     } else {
5251         idxStride = 4;
5252     }
5253
5254     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
5255         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
5256         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5257     }
5258
5259     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
5260                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5261
5262     return WINED3D_OK;
5263 }
5264
5265 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5266                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5267                                                     UINT VertexStreamZeroStride) {
5268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5269     IWineD3DVertexBuffer *vb;
5270
5271     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5272              debug_d3dprimitivetype(PrimitiveType),
5273              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5274
5275     if(!This->stateBlock->vertexDecl) {
5276         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5277         return WINED3DERR_INVALIDCALL;
5278     }
5279
5280     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5281     vb = This->stateBlock->streamSource[0];
5282     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5283     if(vb) IWineD3DVertexBuffer_Release(vb);
5284     This->stateBlock->streamOffset[0] = 0;
5285     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5286     This->stateBlock->streamIsUP = TRUE;
5287     This->stateBlock->loadBaseVertexIndex = 0;
5288
5289     /* TODO: Only mark dirty if drawing from a different UP address */
5290     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5291
5292     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
5293                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5294
5295     /* MSDN specifies stream zero settings must be set to NULL */
5296     This->stateBlock->streamStride[0] = 0;
5297     This->stateBlock->streamSource[0] = NULL;
5298
5299     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5300      * the new stream sources or use UP drawing again
5301      */
5302     return WINED3D_OK;
5303 }
5304
5305 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5306                                                              UINT MinVertexIndex, UINT NumVertices,
5307                                                              UINT PrimitiveCount, CONST void* pIndexData,
5308                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5309                                                              UINT VertexStreamZeroStride) {
5310     int                 idxStride;
5311     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5312     IWineD3DVertexBuffer *vb;
5313     IWineD3DIndexBuffer *ib;
5314
5315     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5316              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5317              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5318              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5319
5320     if(!This->stateBlock->vertexDecl) {
5321         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5322         return WINED3DERR_INVALIDCALL;
5323     }
5324
5325     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5326         idxStride = 2;
5327     } else {
5328         idxStride = 4;
5329     }
5330
5331     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5332     vb = This->stateBlock->streamSource[0];
5333     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5334     if(vb) IWineD3DVertexBuffer_Release(vb);
5335     This->stateBlock->streamIsUP = TRUE;
5336     This->stateBlock->streamOffset[0] = 0;
5337     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5338
5339     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5340     This->stateBlock->baseVertexIndex = 0;
5341     This->stateBlock->loadBaseVertexIndex = 0;
5342     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5343     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5344     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5345
5346     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5347
5348     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5349     This->stateBlock->streamSource[0] = NULL;
5350     This->stateBlock->streamStride[0] = 0;
5351     ib = This->stateBlock->pIndexData;
5352     if(ib) {
5353         IWineD3DIndexBuffer_Release(ib);
5354         This->stateBlock->pIndexData = NULL;
5355     }
5356     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5357      * SetStreamSource to specify a vertex buffer
5358      */
5359
5360     return WINED3D_OK;
5361 }
5362
5363 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5364     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5365
5366     /* Mark the state dirty until we have nicer tracking
5367      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5368      * that value.
5369      */
5370     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5371     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5372     This->stateBlock->baseVertexIndex = 0;
5373     This->up_strided = DrawPrimStrideData;
5374     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
5375     This->up_strided = NULL;
5376     return WINED3D_OK;
5377 }
5378
5379 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData, UINT NumVertices, CONST void *pIndexData, WINED3DFORMAT IndexDataFormat) {
5380     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5381     DWORD idxSize = (IndexDataFormat == WINED3DFMT_INDEX32 ? 4 : 2);
5382
5383     /* Mark the state dirty until we have nicer tracking
5384      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5385      * that value.
5386      */
5387     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5388     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5389     This->stateBlock->streamIsUP = TRUE;
5390     This->stateBlock->baseVertexIndex = 0;
5391     This->up_strided = DrawPrimStrideData;
5392     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
5393     This->up_strided = NULL;
5394     return WINED3D_OK;
5395 }
5396
5397 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
5398     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5399      * not callable by the app directly no parameter validation checks are needed here.
5400      */
5401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5402     WINED3DLOCKED_BOX src;
5403     WINED3DLOCKED_BOX dst;
5404     HRESULT hr;
5405     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
5406
5407     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5408      * dirtification to improve loading performance.
5409      */
5410     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
5411     if(FAILED(hr)) return hr;
5412     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
5413     if(FAILED(hr)) {
5414     IWineD3DVolume_UnlockBox(pSourceVolume);
5415             return hr;
5416     }
5417
5418     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
5419
5420     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
5421     if(FAILED(hr)) {
5422         IWineD3DVolume_UnlockBox(pSourceVolume);
5423     } else {
5424         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
5425     }
5426     return hr;
5427 }
5428
5429 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5430 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5431     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5432     HRESULT hr = WINED3D_OK;
5433     WINED3DRESOURCETYPE sourceType;
5434     WINED3DRESOURCETYPE destinationType;
5435     int i ,levels;
5436
5437     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5438
5439     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5440
5441     /* verify that the source and destination textures aren't NULL */
5442     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5443         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5444              This, pSourceTexture, pDestinationTexture);
5445         hr = WINED3DERR_INVALIDCALL;
5446     }
5447
5448     if (pSourceTexture == pDestinationTexture) {
5449         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5450              This, pSourceTexture, pDestinationTexture);
5451         hr = WINED3DERR_INVALIDCALL;
5452     }
5453     /* Verify that the source and destination textures are the same type */
5454     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5455     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5456
5457     if (sourceType != destinationType) {
5458         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5459              This);
5460         hr = WINED3DERR_INVALIDCALL;
5461     }
5462
5463     /* check that both textures have the identical numbers of levels  */
5464     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5465         WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5466         hr = WINED3DERR_INVALIDCALL;
5467     }
5468
5469     if (WINED3D_OK == hr) {
5470
5471         /* Make sure that the destination texture is loaded */
5472         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5473
5474         /* Update every surface level of the texture */
5475         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5476
5477         switch (sourceType) {
5478         case WINED3DRTYPE_TEXTURE:
5479             {
5480                 IWineD3DSurface *srcSurface;
5481                 IWineD3DSurface *destSurface;
5482
5483                 for (i = 0 ; i < levels ; ++i) {
5484                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5485                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5486                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5487                     IWineD3DSurface_Release(srcSurface);
5488                     IWineD3DSurface_Release(destSurface);
5489                     if (WINED3D_OK != hr) {
5490                         WARN("(%p) : Call to update surface failed\n", This);
5491                         return hr;
5492                     }
5493                 }
5494             }
5495             break;
5496         case WINED3DRTYPE_CUBETEXTURE:
5497             {
5498                 IWineD3DSurface *srcSurface;
5499                 IWineD3DSurface *destSurface;
5500                 WINED3DCUBEMAP_FACES faceType;
5501
5502                 for (i = 0 ; i < levels ; ++i) {
5503                     /* Update each cube face */
5504                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5505                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5506                         if (WINED3D_OK != hr) {
5507                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5508                         } else {
5509                             TRACE("Got srcSurface %p\n", srcSurface);
5510                         }
5511                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5512                         if (WINED3D_OK != hr) {
5513                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5514                         } else {
5515                             TRACE("Got desrSurface %p\n", destSurface);
5516                         }
5517                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5518                         IWineD3DSurface_Release(srcSurface);
5519                         IWineD3DSurface_Release(destSurface);
5520                         if (WINED3D_OK != hr) {
5521                             WARN("(%p) : Call to update surface failed\n", This);
5522                             return hr;
5523                         }
5524                     }
5525                 }
5526             }
5527             break;
5528
5529         case WINED3DRTYPE_VOLUMETEXTURE:
5530             {
5531                 IWineD3DVolume  *srcVolume  = NULL;
5532                 IWineD3DVolume  *destVolume = NULL;
5533
5534                 for (i = 0 ; i < levels ; ++i) {
5535                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5536                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5537                     hr =  IWineD3DDeviceImpl_UpdateVolume(iface, srcVolume, destVolume);
5538                     IWineD3DVolume_Release(srcVolume);
5539                     IWineD3DVolume_Release(destVolume);
5540                     if (WINED3D_OK != hr) {
5541                         WARN("(%p) : Call to update volume failed\n", This);
5542                         return hr;
5543                     }
5544                 }
5545             }
5546             break;
5547
5548         default:
5549             FIXME("(%p) : Unsupported source and destination type\n", This);
5550             hr = WINED3DERR_INVALIDCALL;
5551         }
5552     }
5553
5554     return hr;
5555 }
5556
5557 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5558     IWineD3DSwapChain *swapChain;
5559     HRESULT hr;
5560     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5561     if(hr == WINED3D_OK) {
5562         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5563                 IWineD3DSwapChain_Release(swapChain);
5564     }
5565     return hr;
5566 }
5567
5568 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5569     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5570     /* return a sensible default */
5571     *pNumPasses = 1;
5572     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5573     FIXME("(%p) : stub\n", This);
5574     return WINED3D_OK;
5575 }
5576
5577 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5578 {
5579     int i;
5580
5581     for (i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5582             IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5583             if (texture && (texture->resource.format == WINED3DFMT_P8 || texture->resource.format == WINED3DFMT_A8P8)) {
5584                 IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5585             }
5586         }
5587 }
5588
5589 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5590     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5591     int j;
5592     UINT NewSize;
5593     PALETTEENTRY **palettes;
5594
5595     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5596
5597     if (PaletteNumber >= MAX_PALETTES) {
5598         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5599         return WINED3DERR_INVALIDCALL;
5600     }
5601
5602     if (PaletteNumber >= This->NumberOfPalettes) {
5603         NewSize = This->NumberOfPalettes;
5604         do {
5605            NewSize *= 2;
5606         } while(PaletteNumber >= NewSize);
5607         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5608         if (!palettes) {
5609             ERR("Out of memory!\n");
5610             return E_OUTOFMEMORY;
5611         }
5612         This->palettes = palettes;
5613         This->NumberOfPalettes = NewSize;
5614     }
5615
5616     if (!This->palettes[PaletteNumber]) {
5617         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5618         if (!This->palettes[PaletteNumber]) {
5619             ERR("Out of memory!\n");
5620             return E_OUTOFMEMORY;
5621         }
5622     }
5623
5624     for (j = 0; j < 256; ++j) {
5625         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5626         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5627         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5628         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5629     }
5630     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5631     TRACE("(%p) : returning\n", This);
5632     return WINED3D_OK;
5633 }
5634
5635 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5636     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5637     int j;
5638     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5639     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5640         /* What happens in such situation isn't documented; Native seems to silently abort
5641            on such conditions. Return Invalid Call. */
5642         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5643         return WINED3DERR_INVALIDCALL;
5644     }
5645     for (j = 0; j < 256; ++j) {
5646         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5647         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5648         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5649         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5650     }
5651     TRACE("(%p) : returning\n", This);
5652     return WINED3D_OK;
5653 }
5654
5655 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5657     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5658     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5659        (tested with reference rasterizer). Return Invalid Call. */
5660     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5661         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5662         return WINED3DERR_INVALIDCALL;
5663     }
5664     /*TODO: stateblocks */
5665     if (This->currentPalette != PaletteNumber) {
5666         This->currentPalette = PaletteNumber;
5667         dirtify_p8_texture_samplers(This);
5668     }
5669     TRACE("(%p) : returning\n", This);
5670     return WINED3D_OK;
5671 }
5672
5673 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5674     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5675     if (PaletteNumber == NULL) {
5676         WARN("(%p) : returning Invalid Call\n", This);
5677         return WINED3DERR_INVALIDCALL;
5678     }
5679     /*TODO: stateblocks */
5680     *PaletteNumber = This->currentPalette;
5681     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5682     return WINED3D_OK;
5683 }
5684
5685 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5686     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5687     static BOOL showFixmes = TRUE;
5688     if (showFixmes) {
5689         FIXME("(%p) : stub\n", This);
5690         showFixmes = FALSE;
5691     }
5692
5693     This->softwareVertexProcessing = bSoftware;
5694     return WINED3D_OK;
5695 }
5696
5697
5698 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5699     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5700     static BOOL showFixmes = TRUE;
5701     if (showFixmes) {
5702         FIXME("(%p) : stub\n", This);
5703         showFixmes = FALSE;
5704     }
5705     return This->softwareVertexProcessing;
5706 }
5707
5708
5709 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5710     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5711     IWineD3DSwapChain *swapChain;
5712     HRESULT hr;
5713
5714     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5715
5716     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5717     if(hr == WINED3D_OK){
5718         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5719         IWineD3DSwapChain_Release(swapChain);
5720     }else{
5721         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5722     }
5723     return hr;
5724 }
5725
5726
5727 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5728     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5729     static BOOL showfixmes = TRUE;
5730     if(nSegments != 0.0f) {
5731         if( showfixmes) {
5732             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5733             showfixmes = FALSE;
5734         }
5735     }
5736     return WINED3D_OK;
5737 }
5738
5739 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5740     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5741     static BOOL showfixmes = TRUE;
5742     if( showfixmes) {
5743         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5744         showfixmes = FALSE;
5745     }
5746     return 0.0f;
5747 }
5748
5749 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5750     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5751     /** TODO: remove casts to IWineD3DSurfaceImpl
5752      *       NOTE: move code to surface to accomplish this
5753       ****************************************/
5754     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5755     int srcWidth, srcHeight;
5756     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5757     WINED3DFORMAT destFormat, srcFormat;
5758     UINT          destSize;
5759     int srcLeft, destLeft, destTop;
5760     WINED3DPOOL       srcPool, destPool;
5761     int offset    = 0;
5762     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5763     glDescriptor *glDescription = NULL;
5764     GLenum dummy;
5765     int sampler;
5766     int bpp;
5767     CONVERT_TYPES convert = NO_CONVERSION;
5768
5769     WINED3DSURFACE_DESC  winedesc;
5770
5771     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5772     memset(&winedesc, 0, sizeof(winedesc));
5773     winedesc.Width  = &srcSurfaceWidth;
5774     winedesc.Height = &srcSurfaceHeight;
5775     winedesc.Pool   = &srcPool;
5776     winedesc.Format = &srcFormat;
5777
5778     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5779
5780     winedesc.Width  = &destSurfaceWidth;
5781     winedesc.Height = &destSurfaceHeight;
5782     winedesc.Pool   = &destPool;
5783     winedesc.Format = &destFormat;
5784     winedesc.Size   = &destSize;
5785
5786     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5787
5788     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5789         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5790         return WINED3DERR_INVALIDCALL;
5791     }
5792
5793     /* This call loads the opengl surface directly, instead of copying the surface to the
5794      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5795      * copy in sysmem and use regular surface loading.
5796      */
5797     d3dfmt_get_conv((IWineD3DSurfaceImpl *) pDestinationSurface, FALSE, TRUE,
5798                     &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5799     if(convert != NO_CONVERSION) {
5800         return IWineD3DSurface_BltFast(pDestinationSurface,
5801                                         pDestPoint  ? pDestPoint->x : 0,
5802                                         pDestPoint  ? pDestPoint->y : 0,
5803                                         pSourceSurface, (RECT *) pSourceRect, 0);
5804     }
5805
5806     if (destFormat == WINED3DFMT_UNKNOWN) {
5807         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5808         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5809
5810         /* Get the update surface description */
5811         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5812     }
5813
5814     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5815
5816     ENTER_GL();
5817
5818     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5819         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5820         checkGLcall("glActiveTextureARB");
5821     }
5822
5823     /* Make sure the surface is loaded and up to date */
5824     IWineD3DSurface_PreLoad(pDestinationSurface);
5825
5826     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5827
5828     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5829     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5830     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5831     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5832     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5833     destTop    = pDestPoint  ? pDestPoint->y : 0;
5834
5835
5836     /* This function doesn't support compressed textures
5837     the pitch is just bytesPerPixel * width */
5838     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5839         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5840         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5841         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5842     }
5843     /* TODO DXT formats */
5844
5845     if(pSourceRect != NULL && pSourceRect->top != 0){
5846        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5847     }
5848     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5849     ,This
5850     ,glDescription->level
5851     ,destLeft
5852     ,destTop
5853     ,srcWidth
5854     ,srcHeight
5855     ,glDescription->glFormat
5856     ,glDescription->glType
5857     ,IWineD3DSurface_GetData(pSourceSurface)
5858     );
5859
5860     /* Sanity check */
5861     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5862
5863         /* need to lock the surface to get the data */
5864         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5865     }
5866
5867     /* TODO: Cube and volume support */
5868     if(rowoffset != 0){
5869         /* not a whole row so we have to do it a line at a time */
5870         int j;
5871
5872         /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5873         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5874
5875         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5876
5877                 glTexSubImage2D(glDescription->target
5878                     ,glDescription->level
5879                     ,destLeft
5880                     ,j
5881                     ,srcWidth
5882                     ,1
5883                     ,glDescription->glFormat
5884                     ,glDescription->glType
5885                     ,data /* could be quicker using */
5886                 );
5887             data += rowoffset;
5888         }
5889
5890     } else { /* Full width, so just write out the whole texture */
5891
5892         if (WINED3DFMT_DXT1 == destFormat ||
5893             WINED3DFMT_DXT2 == destFormat ||
5894             WINED3DFMT_DXT3 == destFormat ||
5895             WINED3DFMT_DXT4 == destFormat ||
5896             WINED3DFMT_DXT5 == destFormat) {
5897             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5898                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5899                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5900                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5901                 } if (destFormat != srcFormat) {
5902                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5903                 } else {
5904                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5905                                                         glDescription->level,
5906                                                         glDescription->glFormatInternal,
5907                                                         srcWidth,
5908                                                         srcHeight,
5909                                                         0,
5910                                                         destSize,
5911                                                         IWineD3DSurface_GetData(pSourceSurface));
5912                 }
5913             } else {
5914                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5915             }
5916
5917
5918         } else {
5919             glTexSubImage2D(glDescription->target
5920                     ,glDescription->level
5921                     ,destLeft
5922                     ,destTop
5923                     ,srcWidth
5924                     ,srcHeight
5925                     ,glDescription->glFormat
5926                     ,glDescription->glType
5927                     ,IWineD3DSurface_GetData(pSourceSurface)
5928                 );
5929         }
5930      }
5931     checkGLcall("glTexSubImage2D");
5932
5933     LEAVE_GL();
5934
5935     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5936     sampler = This->rev_tex_unit_map[0];
5937     if (sampler != -1) {
5938         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5939     }
5940
5941     return WINED3D_OK;
5942 }
5943
5944 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5945     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5946     struct WineD3DRectPatch *patch;
5947     unsigned int i;
5948     struct list *e;
5949     BOOL found;
5950     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5951
5952     if(!(Handle || pRectPatchInfo)) {
5953         /* TODO: Write a test for the return value, thus the FIXME */
5954         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5955         return WINED3DERR_INVALIDCALL;
5956     }
5957
5958     if(Handle) {
5959         i = PATCHMAP_HASHFUNC(Handle);
5960         found = FALSE;
5961         LIST_FOR_EACH(e, &This->patches[i]) {
5962             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5963             if(patch->Handle == Handle) {
5964                 found = TRUE;
5965                 break;
5966             }
5967         }
5968
5969         if(!found) {
5970             TRACE("Patch does not exist. Creating a new one\n");
5971             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5972             patch->Handle = Handle;
5973             list_add_head(&This->patches[i], &patch->entry);
5974         } else {
5975             TRACE("Found existing patch %p\n", patch);
5976         }
5977     } else {
5978         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5979          * attributes we have to tesselate, read back, and draw. This needs a patch
5980          * management structure instance. Create one.
5981          *
5982          * A possible improvement is to check if a vertex shader is used, and if not directly
5983          * draw the patch.
5984          */
5985         FIXME("Drawing an uncached patch. This is slow\n");
5986         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5987     }
5988
5989     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5990        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5991        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5992         HRESULT hr;
5993         TRACE("Tesselation density or patch info changed, retesselating\n");
5994
5995         if(pRectPatchInfo) {
5996             patch->RectPatchInfo = *pRectPatchInfo;
5997         }
5998         patch->numSegs[0] = pNumSegs[0];
5999         patch->numSegs[1] = pNumSegs[1];
6000         patch->numSegs[2] = pNumSegs[2];
6001         patch->numSegs[3] = pNumSegs[3];
6002
6003         hr = tesselate_rectpatch(This, patch);
6004         if(FAILED(hr)) {
6005             WARN("Patch tesselation failed\n");
6006
6007             /* Do not release the handle to store the params of the patch */
6008             if(!Handle) {
6009                 HeapFree(GetProcessHeap(), 0, patch);
6010             }
6011             return hr;
6012         }
6013     }
6014
6015     This->currentPatch = patch;
6016     IWineD3DDevice_DrawPrimitiveStrided(iface, WINED3DPT_TRIANGLELIST, patch->numSegs[0] * patch->numSegs[1] * 2, &patch->strided);
6017     This->currentPatch = NULL;
6018
6019     /* Destroy uncached patches */
6020     if(!Handle) {
6021         HeapFree(GetProcessHeap(), 0, patch->mem);
6022         HeapFree(GetProcessHeap(), 0, patch);
6023     }
6024     return WINED3D_OK;
6025 }
6026
6027 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6028     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6029     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6030     FIXME("(%p) : Stub\n", This);
6031     return WINED3D_OK;
6032 }
6033
6034 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6035     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6036     int i;
6037     struct WineD3DRectPatch *patch;
6038     struct list *e;
6039     TRACE("(%p) Handle(%d)\n", This, Handle);
6040
6041     i = PATCHMAP_HASHFUNC(Handle);
6042     LIST_FOR_EACH(e, &This->patches[i]) {
6043         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
6044         if(patch->Handle == Handle) {
6045             TRACE("Deleting patch %p\n", patch);
6046             list_remove(&patch->entry);
6047             HeapFree(GetProcessHeap(), 0, patch->mem);
6048             HeapFree(GetProcessHeap(), 0, patch);
6049             return WINED3D_OK;
6050         }
6051     }
6052
6053     /* TODO: Write a test for the return value */
6054     FIXME("Attempt to destroy nonexistent patch\n");
6055     return WINED3DERR_INVALIDCALL;
6056 }
6057
6058 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
6059     HRESULT hr;
6060     IWineD3DSwapChain *swapchain;
6061
6062     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
6063     if (SUCCEEDED(hr)) {
6064         IWineD3DSwapChain_Release((IUnknown *)swapchain);
6065         return swapchain;
6066     }
6067
6068     return NULL;
6069 }
6070
6071 void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
6072     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6073
6074     if (!*fbo) {
6075         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
6076         checkGLcall("glGenFramebuffersEXT()");
6077     }
6078     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
6079     checkGLcall("glBindFramebuffer()");
6080 }
6081
6082 /* TODO: Handle stencil attachments */
6083 void attach_depth_stencil_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) {
6084     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6085
6086     if (use_render_buffer && depth_stencil_impl->current_renderbuffer) {
6087         GL_EXTCALL(glFramebufferRenderbufferEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
6088         checkGLcall("glFramebufferRenderbufferEXT()");
6089     } else {
6090         IWineD3DBaseTextureImpl *texture_impl;
6091         GLenum texttarget, target;
6092         GLint old_binding = 0;
6093
6094         texttarget = depth_stencil_impl->glDescription.target;
6095         if(texttarget == GL_TEXTURE_2D) {
6096             target = GL_TEXTURE_2D;
6097             glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
6098         } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
6099             target = GL_TEXTURE_RECTANGLE_ARB;
6100             glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
6101         } else {
6102             target = GL_TEXTURE_CUBE_MAP_ARB;
6103             glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
6104         }
6105
6106         IWineD3DSurface_PreLoad(depth_stencil);
6107
6108         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6109         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6110         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
6111         glBindTexture(target, old_binding);
6112
6113         /* Update base texture states array */
6114         if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
6115             texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
6116             texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
6117             if (texture_impl->baseTexture.bindCount) {
6118                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
6119             }
6120
6121             IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
6122         }
6123
6124         GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, texttarget,
6125                     depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level));
6126         checkGLcall("glFramebufferTexture2DEXT()");
6127     }
6128 }
6129
6130 void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
6131     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
6132     IWineD3DBaseTextureImpl *texture_impl;
6133     GLenum texttarget, target;
6134     GLint old_binding;
6135
6136     texttarget = surface_impl->glDescription.target;
6137     if(texttarget == GL_TEXTURE_2D) {
6138         target = GL_TEXTURE_2D;
6139         glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
6140     } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
6141         target = GL_TEXTURE_RECTANGLE_ARB;
6142         glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
6143     } else {
6144         target = GL_TEXTURE_CUBE_MAP_ARB;
6145         glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
6146     }
6147
6148     IWineD3DSurface_PreLoad(surface);
6149
6150     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6151     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6152     glBindTexture(target, old_binding);
6153
6154     /* Update base texture states array */
6155     if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
6156         texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
6157         texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
6158         if (texture_impl->baseTexture.bindCount) {
6159             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
6160         }
6161
6162         IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
6163     }
6164
6165     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget,
6166             surface_impl->glDescription.textureName, surface_impl->glDescription.level));
6167
6168     checkGLcall("attach_surface_fbo");
6169 }
6170
6171 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
6172     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6173     IWineD3DSwapChain *swapchain;
6174
6175     swapchain = get_swapchain(surface);
6176     if (swapchain) {
6177         GLenum buffer;
6178
6179         TRACE("Surface %p is onscreen\n", surface);
6180
6181         ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD);
6182         ENTER_GL();
6183         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6184         buffer = surface_get_gl_buffer(surface, swapchain);
6185         glDrawBuffer(buffer);
6186         checkGLcall("glDrawBuffer()");
6187     } else {
6188         TRACE("Surface %p is offscreen\n", surface);
6189
6190         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6191         ENTER_GL();
6192         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
6193         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
6194         GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
6195         checkGLcall("glFramebufferRenderbufferEXT");
6196     }
6197
6198     if (rect) {
6199         glEnable(GL_SCISSOR_TEST);
6200         if(!swapchain) {
6201             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
6202         } else {
6203             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
6204                     rect->x2 - rect->x1, rect->y2 - rect->y1);
6205         }
6206         checkGLcall("glScissor");
6207         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
6208     } else {
6209         glDisable(GL_SCISSOR_TEST);
6210     }
6211     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6212
6213     glDisable(GL_BLEND);
6214     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE));
6215
6216     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6217     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
6218
6219     glClearColor(D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color));
6220     glClear(GL_COLOR_BUFFER_BIT);
6221     checkGLcall("glClear");
6222
6223     if (This->render_offscreen) {
6224         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6225     } else {
6226         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6227         checkGLcall("glBindFramebuffer()");
6228     }
6229
6230     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
6231             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
6232         glDrawBuffer(GL_BACK);
6233         checkGLcall("glDrawBuffer()");
6234     }
6235
6236     LEAVE_GL();
6237 }
6238
6239 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
6240     unsigned int r, g, b, a;
6241     DWORD ret;
6242
6243     if(destfmt == WINED3DFMT_A8R8G8B8 || destfmt == WINED3DFMT_X8R8G8B8 ||
6244        destfmt == WINED3DFMT_R8G8B8)
6245         return color;
6246
6247     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
6248
6249     a = (color & 0xff000000) >> 24;
6250     r = (color & 0x00ff0000) >> 16;
6251     g = (color & 0x0000ff00) >>  8;
6252     b = (color & 0x000000ff) >>  0;
6253
6254     switch(destfmt)
6255     {
6256         case WINED3DFMT_R5G6B5:
6257             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
6258             r = (r * 32) / 256;
6259             g = (g * 64) / 256;
6260             b = (b * 32) / 256;
6261             ret  = r << 11;
6262             ret |= g << 5;
6263             ret |= b;
6264             TRACE("Returning %08x\n", ret);
6265             return ret;
6266
6267         case WINED3DFMT_X1R5G5B5:
6268         case WINED3DFMT_A1R5G5B5:
6269             a = (a *  2) / 256;
6270             r = (r * 32) / 256;
6271             g = (g * 32) / 256;
6272             b = (b * 32) / 256;
6273             ret  = a << 15;
6274             ret |= r << 10;
6275             ret |= g <<  5;
6276             ret |= b <<  0;
6277             TRACE("Returning %08x\n", ret);
6278             return ret;
6279
6280         case WINED3DFMT_A8:
6281             TRACE("Returning %08x\n", a);
6282             return a;
6283
6284         case WINED3DFMT_X4R4G4B4:
6285         case WINED3DFMT_A4R4G4B4:
6286             a = (a * 16) / 256;
6287             r = (r * 16) / 256;
6288             g = (g * 16) / 256;
6289             b = (b * 16) / 256;
6290             ret  = a << 12;
6291             ret |= r <<  8;
6292             ret |= g <<  4;
6293             ret |= b <<  0;
6294             TRACE("Returning %08x\n", ret);
6295             return ret;
6296
6297         case WINED3DFMT_R3G3B2:
6298             r = (r * 8) / 256;
6299             g = (g * 8) / 256;
6300             b = (b * 4) / 256;
6301             ret  = r <<  5;
6302             ret |= g <<  2;
6303             ret |= b <<  0;
6304             TRACE("Returning %08x\n", ret);
6305             return ret;
6306
6307         case WINED3DFMT_X8B8G8R8:
6308         case WINED3DFMT_A8B8G8R8:
6309             ret  = a << 24;
6310             ret |= b << 16;
6311             ret |= g <<  8;
6312             ret |= r <<  0;
6313             TRACE("Returning %08x\n", ret);
6314             return ret;
6315
6316         case WINED3DFMT_A2R10G10B10:
6317             a = (a *    4) / 256;
6318             r = (r * 1024) / 256;
6319             g = (g * 1024) / 256;
6320             b = (b * 1024) / 256;
6321             ret  = a << 30;
6322             ret |= r << 20;
6323             ret |= g << 10;
6324             ret |= b <<  0;
6325             TRACE("Returning %08x\n", ret);
6326             return ret;
6327
6328         case WINED3DFMT_A2B10G10R10:
6329             a = (a *    4) / 256;
6330             r = (r * 1024) / 256;
6331             g = (g * 1024) / 256;
6332             b = (b * 1024) / 256;
6333             ret  = a << 30;
6334             ret |= b << 20;
6335             ret |= g << 10;
6336             ret |= r <<  0;
6337             TRACE("Returning %08x\n", ret);
6338             return ret;
6339
6340         default:
6341             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
6342             return 0;
6343     }
6344 }
6345
6346 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6347     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6348     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6349     WINEDDBLTFX BltFx;
6350     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
6351
6352     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6353         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6354         return WINED3DERR_INVALIDCALL;
6355     }
6356
6357     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6358         color_fill_fbo(iface, pSurface, pRect, color);
6359         return WINED3D_OK;
6360     } else {
6361         /* Just forward this to the DirectDraw blitting engine */
6362         memset(&BltFx, 0, sizeof(BltFx));
6363         BltFx.dwSize = sizeof(BltFx);
6364         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format);
6365         return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
6366     }
6367 }
6368
6369 /* rendertarget and depth stencil functions */
6370 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6371     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6372
6373     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6374         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
6375         return WINED3DERR_INVALIDCALL;
6376     }
6377
6378     *ppRenderTarget = This->render_targets[RenderTargetIndex];
6379     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6380     /* Note inc ref on returned surface */
6381     if(*ppRenderTarget != NULL)
6382         IWineD3DSurface_AddRef(*ppRenderTarget);
6383     return WINED3D_OK;
6384 }
6385
6386 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6387     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6388     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6389     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6390     IWineD3DSwapChainImpl *Swapchain;
6391     HRESULT hr;
6392
6393     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6394
6395     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6396     if(hr != WINED3D_OK) {
6397         ERR("Can't get the swapchain\n");
6398         return hr;
6399     }
6400
6401     /* Make sure to release the swapchain */
6402     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6403
6404     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6405         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6406         return WINED3DERR_INVALIDCALL;
6407     }
6408     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6409         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6410         return WINED3DERR_INVALIDCALL;
6411     }
6412
6413     if(Swapchain->frontBuffer != Front) {
6414         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6415
6416         if(Swapchain->frontBuffer)
6417             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6418         Swapchain->frontBuffer = Front;
6419
6420         if(Swapchain->frontBuffer) {
6421             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6422         }
6423     }
6424
6425     if(Back && !Swapchain->backBuffer) {
6426         /* We need memory for the back buffer array - only one back buffer this way */
6427         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6428         if(!Swapchain->backBuffer) {
6429             ERR("Out of memory\n");
6430             return E_OUTOFMEMORY;
6431         }
6432     }
6433
6434     if(Swapchain->backBuffer[0] != Back) {
6435         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6436
6437         /* What to do about the context here in the case of multithreading? Not sure.
6438          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6439          */
6440         ENTER_GL();
6441         if(!Swapchain->backBuffer[0]) {
6442             /* GL was told to draw to the front buffer at creation,
6443              * undo that
6444              */
6445             glDrawBuffer(GL_BACK);
6446             checkGLcall("glDrawBuffer(GL_BACK)");
6447             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6448             Swapchain->presentParms.BackBufferCount = 1;
6449         } else if (!Back) {
6450             /* That makes problems - disable for now */
6451             /* glDrawBuffer(GL_FRONT); */
6452             checkGLcall("glDrawBuffer(GL_FRONT)");
6453             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6454             Swapchain->presentParms.BackBufferCount = 0;
6455         }
6456         LEAVE_GL();
6457
6458         if(Swapchain->backBuffer[0])
6459             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6460         Swapchain->backBuffer[0] = Back;
6461
6462         if(Swapchain->backBuffer[0]) {
6463             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6464         } else {
6465             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6466             Swapchain->backBuffer = NULL;
6467         }
6468
6469     }
6470
6471     return WINED3D_OK;
6472 }
6473
6474 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6475     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6476     *ppZStencilSurface = This->stencilBufferTarget;
6477     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6478
6479     if(*ppZStencilSurface != NULL) {
6480         /* Note inc ref on returned surface */
6481         IWineD3DSurface_AddRef(*ppZStencilSurface);
6482         return WINED3D_OK;
6483     } else {
6484         return WINED3DERR_NOTFOUND;
6485     }
6486 }
6487
6488 /* TODO: Handle stencil attachments */
6489 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6490     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6491
6492     TRACE("Set depth stencil to %p\n", depth_stencil);
6493
6494     if (depth_stencil) {
6495         attach_depth_stencil_fbo(This, GL_FRAMEBUFFER_EXT, depth_stencil, TRUE);
6496     } else {
6497         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
6498         checkGLcall("glFramebufferTexture2DEXT()");
6499     }
6500 }
6501
6502 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
6503     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6504
6505     TRACE("Set render target %u to %p\n", idx, render_target);
6506
6507     if (render_target) {
6508         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
6509         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
6510     } else {
6511         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
6512         checkGLcall("glFramebufferTexture2DEXT()");
6513
6514         This->draw_buffers[idx] = GL_NONE;
6515     }
6516 }
6517
6518 static void check_fbo_status(IWineD3DDevice *iface) {
6519     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6520     GLenum status;
6521
6522     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
6523     if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
6524         TRACE("FBO complete\n");
6525     } else {
6526         IWineD3DSurfaceImpl *attachment;
6527         int i;
6528         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
6529
6530         /* Dump the FBO attachments */
6531         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6532             attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
6533             if (attachment) {
6534                 FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
6535                         attachment->pow2Width, attachment->pow2Height);
6536             }
6537         }
6538         attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
6539         if (attachment) {
6540             FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
6541                     attachment->pow2Width, attachment->pow2Height);
6542         }
6543     }
6544 }
6545
6546 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
6547     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6548     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
6549     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
6550
6551     if (!ds_impl) return FALSE;
6552
6553     if (ds_impl->current_renderbuffer) {
6554         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
6555                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
6556     }
6557
6558     return (rt_impl->pow2Width != ds_impl->pow2Width ||
6559             rt_impl->pow2Height != ds_impl->pow2Height);
6560 }
6561
6562 void apply_fbo_state(IWineD3DDevice *iface) {
6563     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6564     unsigned int i;
6565
6566     if (This->render_offscreen) {
6567         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6568
6569         /* Apply render targets */
6570         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6571             IWineD3DSurface *render_target = This->render_targets[i];
6572             if (This->fbo_color_attachments[i] != render_target) {
6573                 set_render_target_fbo(iface, i, render_target);
6574                 This->fbo_color_attachments[i] = render_target;
6575             }
6576         }
6577
6578         /* Apply depth targets */
6579         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
6580             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
6581             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
6582
6583             if (This->stencilBufferTarget) {
6584                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
6585             }
6586             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
6587             This->fbo_depth_attachment = This->stencilBufferTarget;
6588         }
6589     } else {
6590         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6591     }
6592
6593     check_fbo_status(iface);
6594 }
6595
6596 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6597         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
6598     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6599     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6600     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6601     GLenum gl_filter;
6602     POINT offset = {0, 0};
6603
6604     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6605             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6606     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6607     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6608
6609     switch (filter) {
6610         case WINED3DTEXF_LINEAR:
6611             gl_filter = GL_LINEAR;
6612             break;
6613
6614         default:
6615             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6616         case WINED3DTEXF_NONE:
6617         case WINED3DTEXF_POINT:
6618             gl_filter = GL_NEAREST;
6619             break;
6620     }
6621
6622     /* Attach src surface to src fbo */
6623     src_swapchain = get_swapchain(src_surface);
6624     if (src_swapchain) {
6625         GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6626
6627         TRACE("Source surface %p is onscreen\n", src_surface);
6628         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6629         /* Make sure the drawable is up to date. In the offscreen case
6630          * attach_surface_fbo() implicitly takes care of this. */
6631         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
6632
6633         if(buffer == GL_FRONT) {
6634             RECT windowsize;
6635             UINT h;
6636             ClientToScreen(This->ddraw_window, &offset);
6637             GetClientRect(This->ddraw_window, &windowsize);
6638             h = windowsize.bottom - windowsize.top;
6639             src_rect->x1 -= offset.x; src_rect->x2 -=offset.x;
6640             src_rect->y1 =  offset.y + h - src_rect->y1;
6641             src_rect->y2 =  offset.y + h - src_rect->y2;
6642         } else {
6643             src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6644             src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6645         }
6646
6647         ENTER_GL();
6648         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
6649         glReadBuffer(buffer);
6650         checkGLcall("glReadBuffer()");
6651     } else {
6652         TRACE("Source surface %p is offscreen\n", src_surface);
6653         ENTER_GL();
6654         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
6655         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
6656         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
6657         checkGLcall("glReadBuffer()");
6658         GL_EXTCALL(glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
6659         checkGLcall("glFramebufferRenderbufferEXT");
6660     }
6661     LEAVE_GL();
6662
6663     /* Attach dst surface to dst fbo */
6664     dst_swapchain = get_swapchain(dst_surface);
6665     if (dst_swapchain) {
6666         GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6667
6668         TRACE("Destination surface %p is onscreen\n", dst_surface);
6669         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6670         /* Make sure the drawable is up to date. In the offscreen case
6671          * attach_surface_fbo() implicitly takes care of this. */
6672         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
6673
6674         if(buffer == GL_FRONT) {
6675             RECT windowsize;
6676             UINT h;
6677             ClientToScreen(This->ddraw_window, &offset);
6678             GetClientRect(This->ddraw_window, &windowsize);
6679             h = windowsize.bottom - windowsize.top;
6680             dst_rect->x1 -= offset.x; dst_rect->x2 -=offset.x;
6681             dst_rect->y1 =  offset.y + h - dst_rect->y1;
6682             dst_rect->y2 =  offset.y + h - dst_rect->y2;
6683         } else {
6684             /* Screen coords = window coords, surface height = window height */
6685             dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6686             dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6687         }
6688
6689         ENTER_GL();
6690         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
6691         glDrawBuffer(buffer);
6692         checkGLcall("glDrawBuffer()");
6693     } else {
6694         TRACE("Destination surface %p is offscreen\n", dst_surface);
6695
6696         /* No src or dst swapchain? Make sure some context is active(multithreading) */
6697         if(!src_swapchain) {
6698             ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6699         }
6700
6701         ENTER_GL();
6702         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
6703         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
6704         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
6705         checkGLcall("glDrawBuffer()");
6706         GL_EXTCALL(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
6707         checkGLcall("glFramebufferRenderbufferEXT");
6708     }
6709     glDisable(GL_SCISSOR_TEST);
6710     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6711
6712     if (flip) {
6713         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6714                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
6715         checkGLcall("glBlitFramebuffer()");
6716     } else {
6717         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6718                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
6719         checkGLcall("glBlitFramebuffer()");
6720     }
6721
6722     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
6723
6724     if (This->render_offscreen) {
6725         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6726     } else {
6727         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6728         checkGLcall("glBindFramebuffer()");
6729     }
6730
6731     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6732     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6733             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6734         glDrawBuffer(GL_BACK);
6735         checkGLcall("glDrawBuffer()");
6736     }
6737     LEAVE_GL();
6738 }
6739
6740 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6741     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6742     WINED3DVIEWPORT viewport;
6743
6744     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6745
6746     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6747         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6748              This, RenderTargetIndex, GL_LIMITS(buffers));
6749         return WINED3DERR_INVALIDCALL;
6750     }
6751
6752     /* MSDN says that null disables the render target
6753     but a device must always be associated with a render target
6754     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6755     */
6756     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6757         FIXME("Trying to set render target 0 to NULL\n");
6758         return WINED3DERR_INVALIDCALL;
6759     }
6760     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6761         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);
6762         return WINED3DERR_INVALIDCALL;
6763     }
6764
6765     /* If we are trying to set what we already have, don't bother */
6766     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6767         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6768         return WINED3D_OK;
6769     }
6770     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6771     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6772     This->render_targets[RenderTargetIndex] = pRenderTarget;
6773
6774     /* Render target 0 is special */
6775     if(RenderTargetIndex == 0) {
6776         /* Finally, reset the viewport as the MSDN states. */
6777         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6778         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6779         viewport.X      = 0;
6780         viewport.Y      = 0;
6781         viewport.MaxZ   = 1.0f;
6782         viewport.MinZ   = 0.0f;
6783         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6784         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6785          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6786          */
6787         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
6788     }
6789     return WINED3D_OK;
6790 }
6791
6792 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6793     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6794     HRESULT  hr = WINED3D_OK;
6795     IWineD3DSurface *tmp;
6796
6797     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6798
6799     if (pNewZStencil == This->stencilBufferTarget) {
6800         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6801     } else {
6802         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6803         * depending on the renter target implementation being used.
6804         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6805         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6806         * stencil buffer and incur an extra memory overhead
6807          ******************************************************/
6808
6809         if (This->stencilBufferTarget) {
6810             ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
6811             surface_load_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN);
6812             surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN);
6813         }
6814
6815         tmp = This->stencilBufferTarget;
6816         This->stencilBufferTarget = pNewZStencil;
6817         /* should we be calling the parent or the wined3d surface? */
6818         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6819         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6820         hr = WINED3D_OK;
6821
6822         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6823             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6824             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6825             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6826             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6827         }
6828     }
6829
6830     return hr;
6831 }
6832
6833 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6834                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6835     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6836     /* TODO: the use of Impl is deprecated. */
6837     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6838     WINED3DLOCKED_RECT lockedRect;
6839
6840     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6841
6842     /* some basic validation checks */
6843     if(This->cursorTexture) {
6844         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6845         ENTER_GL();
6846         glDeleteTextures(1, &This->cursorTexture);
6847         LEAVE_GL();
6848         This->cursorTexture = 0;
6849     }
6850
6851     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6852         This->haveHardwareCursor = TRUE;
6853     else
6854         This->haveHardwareCursor = FALSE;
6855
6856     if(pCursorBitmap) {
6857         WINED3DLOCKED_RECT rect;
6858
6859         /* MSDN: Cursor must be A8R8G8B8 */
6860         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6861             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6862             return WINED3DERR_INVALIDCALL;
6863         }
6864
6865         /* MSDN: Cursor must be smaller than the display mode */
6866         if(pSur->currentDesc.Width > This->ddraw_width ||
6867            pSur->currentDesc.Height > This->ddraw_height) {
6868             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);
6869             return WINED3DERR_INVALIDCALL;
6870         }
6871
6872         if (!This->haveHardwareCursor) {
6873             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6874
6875             /* Do not store the surface's pointer because the application may
6876              * release it after setting the cursor image. Windows doesn't
6877              * addref the set surface, so we can't do this either without
6878              * creating circular refcount dependencies. Copy out the gl texture
6879              * instead.
6880              */
6881             This->cursorWidth = pSur->currentDesc.Width;
6882             This->cursorHeight = pSur->currentDesc.Height;
6883             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6884             {
6885                 const GlPixelFormatDesc *glDesc;
6886                 const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION, &glDesc);
6887                 char *mem, *bits = (char *)rect.pBits;
6888                 GLint intfmt = glDesc->glInternal;
6889                 GLint format = glDesc->glFormat;
6890                 GLint type = glDesc->glType;
6891                 INT height = This->cursorHeight;
6892                 INT width = This->cursorWidth;
6893                 INT bpp = tableEntry->bpp;
6894                 INT i, sampler;
6895
6896                 /* Reformat the texture memory (pitch and width can be
6897                  * different) */
6898                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6899                 for(i = 0; i < height; i++)
6900                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6901                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6902                 ENTER_GL();
6903
6904                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6905                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6906                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6907                 }
6908
6909                 /* Make sure that a proper texture unit is selected */
6910                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
6911                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6912                     checkGLcall("glActiveTextureARB");
6913                 }
6914                 sampler = This->rev_tex_unit_map[0];
6915                 if (sampler != -1) {
6916                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
6917                 }
6918                 /* Create a new cursor texture */
6919                 glGenTextures(1, &This->cursorTexture);
6920                 checkGLcall("glGenTextures");
6921                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6922                 checkGLcall("glBindTexture");
6923                 /* Copy the bitmap memory into the cursor texture */
6924                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6925                 HeapFree(GetProcessHeap(), 0, mem);
6926                 checkGLcall("glTexImage2D");
6927
6928                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6929                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6930                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6931                 }
6932
6933                 LEAVE_GL();
6934             }
6935             else
6936             {
6937                 FIXME("A cursor texture was not returned.\n");
6938                 This->cursorTexture = 0;
6939             }
6940         }
6941         else
6942         {
6943             /* Draw a hardware cursor */
6944             ICONINFO cursorInfo;
6945             HCURSOR cursor;
6946             /* Create and clear maskBits because it is not needed for
6947              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6948              * chunks. */
6949             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6950                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6951             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6952                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6953                                          WINED3DLOCK_READONLY
6954             );
6955             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6956                   pSur->currentDesc.Height);
6957
6958             cursorInfo.fIcon = FALSE;
6959             cursorInfo.xHotspot = XHotSpot;
6960             cursorInfo.yHotspot = YHotSpot;
6961             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
6962                                               pSur->currentDesc.Height, 1,
6963                                               1, &maskBits);
6964             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
6965                                                pSur->currentDesc.Height, 1,
6966                                                32, lockedRect.pBits);
6967             IWineD3DSurface_UnlockRect(pCursorBitmap);
6968             /* Create our cursor and clean up. */
6969             cursor = CreateIconIndirect(&cursorInfo);
6970             SetCursor(cursor);
6971             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6972             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6973             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6974             This->hardwareCursor = cursor;
6975             HeapFree(GetProcessHeap(), 0, maskBits);
6976         }
6977     }
6978
6979     This->xHotSpot = XHotSpot;
6980     This->yHotSpot = YHotSpot;
6981     return WINED3D_OK;
6982 }
6983
6984 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6985     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6986     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6987
6988     This->xScreenSpace = XScreenSpace;
6989     This->yScreenSpace = YScreenSpace;
6990
6991     return;
6992
6993 }
6994
6995 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6996     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6997     BOOL oldVisible = This->bCursorVisible;
6998     POINT pt;
6999
7000     TRACE("(%p) : visible(%d)\n", This, bShow);
7001
7002     /*
7003      * When ShowCursor is first called it should make the cursor appear at the OS's last
7004      * known cursor position.  Because of this, some applications just repetitively call
7005      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
7006      */
7007     GetCursorPos(&pt);
7008     This->xScreenSpace = pt.x;
7009     This->yScreenSpace = pt.y;
7010
7011     if (This->haveHardwareCursor) {
7012         This->bCursorVisible = bShow;
7013         if (bShow)
7014             SetCursor(This->hardwareCursor);
7015         else
7016             SetCursor(NULL);
7017     }
7018     else
7019     {
7020         if (This->cursorTexture)
7021             This->bCursorVisible = bShow;
7022     }
7023
7024     return oldVisible;
7025 }
7026
7027 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7028     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7029     IWineD3DResourceImpl *resource;
7030     TRACE("(%p) : state (%u)\n", This, This->state);
7031
7032     /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
7033     switch (This->state) {
7034     case WINED3D_OK:
7035         return WINED3D_OK;
7036     case WINED3DERR_DEVICELOST:
7037         {
7038             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
7039                 if (resource->resource.pool == WINED3DPOOL_DEFAULT)
7040                     return WINED3DERR_DEVICENOTRESET;
7041             }
7042             return WINED3DERR_DEVICELOST;
7043         }
7044     case WINED3DERR_DRIVERINTERNALERROR:
7045         return WINED3DERR_DRIVERINTERNALERROR;
7046     }
7047
7048     /* Unknown state */
7049     return WINED3DERR_DRIVERINTERNALERROR;
7050 }
7051
7052
7053 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7054     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7055     /** FIXME: Resource tracking needs to be done,
7056     * The closes we can do to this is set the priorities of all managed textures low
7057     * and then reset them.
7058      ***********************************************************/
7059     FIXME("(%p) : stub\n", This);
7060     return WINED3D_OK;
7061 }
7062
7063 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7064     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
7065
7066     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
7067     if(surface->Flags & SFLAG_DIBSECTION) {
7068         /* Release the DC */
7069         SelectObject(surface->hDC, surface->dib.holdbitmap);
7070         DeleteDC(surface->hDC);
7071         /* Release the DIB section */
7072         DeleteObject(surface->dib.DIBsection);
7073         surface->dib.bitmap_data = NULL;
7074         surface->resource.allocatedMemory = NULL;
7075         surface->Flags &= ~SFLAG_DIBSECTION;
7076     }
7077     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
7078     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
7079     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE) ||
7080         GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) {
7081         surface->pow2Width = pPresentationParameters->BackBufferWidth;
7082         surface->pow2Height = pPresentationParameters->BackBufferHeight;
7083     } else {
7084         surface->pow2Width = surface->pow2Height = 1;
7085         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
7086         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
7087     }
7088     surface->glRect.left = 0;
7089     surface->glRect.top = 0;
7090     surface->glRect.right = surface->pow2Width;
7091     surface->glRect.bottom = surface->pow2Height;
7092
7093     if(surface->glDescription.textureName) {
7094         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
7095         ENTER_GL();
7096         glDeleteTextures(1, &surface->glDescription.textureName);
7097         LEAVE_GL();
7098         surface->glDescription.textureName = 0;
7099         surface->Flags &= ~SFLAG_CLIENT;
7100     }
7101     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
7102        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
7103         surface->Flags |= SFLAG_NONPOW2;
7104     } else  {
7105         surface->Flags &= ~SFLAG_NONPOW2;
7106     }
7107     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
7108     surface->resource.allocatedMemory = NULL;
7109     surface->resource.heapMemory = NULL;
7110     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
7111     /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
7112     if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) {
7113         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INSYSMEM, TRUE);
7114     } else {
7115         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INDRAWABLE, TRUE);
7116     }
7117 }
7118
7119 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
7120     TRACE("Unloading resource %p\n", resource);
7121     IWineD3DResource_UnLoad(resource);
7122     IWineD3DResource_Release(resource);
7123     return S_OK;
7124 }
7125
7126 static void reset_fbo_state(IWineD3DDevice *iface) {
7127     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7128     unsigned int i;
7129
7130     ENTER_GL();
7131     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
7132     checkGLcall("glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)");
7133
7134     if (This->fbo) {
7135         GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
7136         This->fbo = 0;
7137     }
7138     if (This->src_fbo) {
7139         GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
7140         This->src_fbo = 0;
7141     }
7142     if (This->dst_fbo) {
7143         GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
7144         This->dst_fbo = 0;
7145     }
7146     checkGLcall("Tear down FBOs\n");
7147     LEAVE_GL();
7148
7149     for (i = 0; i < GL_LIMITS(buffers); ++i) {
7150         This->fbo_color_attachments[i] = NULL;
7151     }
7152     This->fbo_depth_attachment = NULL;
7153 }
7154
7155 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, WINED3DPRESENT_PARAMETERS *pp) {
7156     UINT i, count;
7157     WINED3DDISPLAYMODE m;
7158     HRESULT hr;
7159
7160     /* All Windowed modes are supported, as is leaving the current mode */
7161     if(pp->Windowed) return TRUE;
7162     if(!pp->BackBufferWidth) return TRUE;
7163     if(!pp->BackBufferHeight) return TRUE;
7164
7165     count = IWineD3D_GetAdapterModeCount(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN);
7166     for(i = 0; i < count; i++) {
7167         memset(&m, 0, sizeof(m));
7168         hr = IWineD3D_EnumAdapterModes(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN, i, &m);
7169         if(FAILED(hr)) {
7170             ERR("EnumAdapterModes failed\n");
7171         }
7172         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
7173             /* Mode found, it is supported */
7174             return TRUE;
7175         }
7176     }
7177     /* Mode not found -> not supported */
7178     return FALSE;
7179 }
7180
7181 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7182     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7183     IWineD3DSwapChainImpl *swapchain;
7184     HRESULT hr;
7185     BOOL DisplayModeChanged = FALSE;
7186     WINED3DDISPLAYMODE mode;
7187     IWineD3DBaseShaderImpl *shader;
7188     IWineD3DSurfaceImpl *target;
7189     UINT i;
7190     TRACE("(%p)\n", This);
7191
7192     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
7193     if(FAILED(hr)) {
7194         ERR("Failed to get the first implicit swapchain\n");
7195         return hr;
7196     }
7197
7198     if(!is_display_mode_supported(This, pPresentationParameters)) {
7199         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
7200         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
7201              pPresentationParameters->BackBufferHeight);
7202         return WINED3DERR_INVALIDCALL;
7203     }
7204
7205     /* Is it necessary to recreate the gl context? Actually every setting can be changed
7206      * on an existing gl context, so there's no real need for recreation.
7207      *
7208      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7209      *
7210      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7211      */
7212     TRACE("New params:\n");
7213     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
7214     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
7215     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
7216     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
7217     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
7218     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
7219     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
7220     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
7221     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
7222     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
7223     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
7224     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
7225     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
7226
7227     /* No special treatment of these parameters. Just store them */
7228     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
7229     swapchain->presentParms.Flags = pPresentationParameters->Flags;
7230     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
7231     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
7232
7233     /* What to do about these? */
7234     if(pPresentationParameters->BackBufferCount != 0 &&
7235         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
7236         ERR("Cannot change the back buffer count yet\n");
7237     }
7238     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
7239         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
7240         ERR("Cannot change the back buffer format yet\n");
7241     }
7242     if(pPresentationParameters->hDeviceWindow != NULL &&
7243         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
7244         ERR("Cannot change the device window yet\n");
7245     }
7246     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
7247         ERR("What do do about a changed auto depth stencil parameter?\n");
7248     }
7249
7250     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
7251         reset_fbo_state((IWineD3DDevice *) This);
7252     }
7253
7254     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
7255     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
7256         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
7257     }
7258
7259     ENTER_GL();
7260     if(This->depth_blt_texture) {
7261         glDeleteTextures(1, &This->depth_blt_texture);
7262         This->depth_blt_texture = 0;
7263     }
7264     if (This->depth_blt_rb) {
7265         GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This->depth_blt_rb));
7266         This->depth_blt_rb = 0;
7267         This->depth_blt_rb_w = 0;
7268         This->depth_blt_rb_h = 0;
7269     }
7270     This->frag_pipe->free_private(iface);
7271     This->shader_backend->shader_free_private(iface);
7272
7273     for (i = 0; i < GL_LIMITS(textures); i++) {
7274         /* Textures are recreated below */
7275         glDeleteTextures(1, &This->dummyTextureName[i]);
7276         checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])");
7277         This->dummyTextureName[i] = 0;
7278     }
7279     LEAVE_GL();
7280
7281     while(This->numContexts) {
7282         DestroyContext(This, This->contexts[0]);
7283     }
7284     This->activeContext = NULL;
7285     HeapFree(GetProcessHeap(), 0, swapchain->context);
7286     swapchain->context = NULL;
7287     swapchain->num_contexts = 0;
7288
7289      if(pPresentationParameters->Windowed) {
7290         mode.Width = swapchain->orig_width;
7291         mode.Height = swapchain->orig_height;
7292         mode.RefreshRate = 0;
7293         mode.Format = swapchain->presentParms.BackBufferFormat;
7294     } else {
7295         mode.Width = pPresentationParameters->BackBufferWidth;
7296         mode.Height = pPresentationParameters->BackBufferHeight;
7297         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
7298         mode.Format = swapchain->presentParms.BackBufferFormat;
7299     }
7300
7301     /* Should Width == 800 && Height == 0 set 800x600? */
7302     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
7303        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
7304         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
7305     {
7306         WINED3DVIEWPORT vp;
7307         int i;
7308
7309         vp.X = 0;
7310         vp.Y = 0;
7311         vp.Width = pPresentationParameters->BackBufferWidth;
7312         vp.Height = pPresentationParameters->BackBufferHeight;
7313         vp.MinZ = 0;
7314         vp.MaxZ = 1;
7315
7316         if(!pPresentationParameters->Windowed) {
7317             DisplayModeChanged = TRUE;
7318         }
7319         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
7320         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
7321
7322         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
7323         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7324             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
7325         }
7326         if(This->auto_depth_stencil_buffer) {
7327             updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters);
7328         }
7329
7330
7331         /* Now set the new viewport */
7332         IWineD3DDevice_SetViewport(iface, &vp);
7333     }
7334
7335     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
7336        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
7337         DisplayModeChanged) {
7338
7339         IWineD3DDevice_SetFullscreen(iface, !pPresentationParameters->Windowed);
7340         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
7341         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
7342     } else if(!pPresentationParameters->Windowed) {
7343         DWORD style = This->style, exStyle = This->exStyle;
7344         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
7345          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
7346          * Reset to clear up their mess. Guild Wars also loses the device during that.
7347          */
7348         This->style = 0;
7349         This->exStyle = 0;
7350         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
7351         This->style = style;
7352         This->exStyle = exStyle;
7353     }
7354
7355     /* Recreate the primary swapchain's context */
7356     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
7357     if(swapchain->backBuffer) {
7358         target = (IWineD3DSurfaceImpl *) swapchain->backBuffer[0];
7359     } else {
7360         target = (IWineD3DSurfaceImpl *) swapchain->frontBuffer;
7361     }
7362     swapchain->context[0] = CreateContext(This, target, swapchain->win_handle, FALSE,
7363                                           &swapchain->presentParms);
7364     swapchain->num_contexts = 1;
7365     This->activeContext = swapchain->context[0];
7366     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
7367
7368     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
7369     if(FAILED(hr)) {
7370         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
7371     }
7372     create_dummy_textures(This);
7373
7374
7375     hr = This->shader_backend->shader_alloc_private(iface);
7376     if(FAILED(hr)) {
7377         ERR("Failed to recreate shader private data\n");
7378         return hr;
7379     }
7380     hr = This->frag_pipe->alloc_private(iface);
7381     if(FAILED(hr)) {
7382         TRACE("Fragment pipeline private data couldn't be allocated\n");
7383         return hr;
7384     }
7385
7386     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
7387      * first use
7388      */
7389     return WINED3D_OK;
7390 }
7391
7392 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7393     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7394     /** FIXME: always true at the moment **/
7395     if(!bEnableDialogs) {
7396         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7397     }
7398     return WINED3D_OK;
7399 }
7400
7401
7402 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7403     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7404     TRACE("(%p) : pParameters %p\n", This, pParameters);
7405
7406     *pParameters = This->createParms;
7407     return WINED3D_OK;
7408 }
7409
7410 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7411     IWineD3DSwapChain *swapchain;
7412
7413     TRACE("Relaying  to swapchain\n");
7414
7415     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
7416         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7417         IWineD3DSwapChain_Release(swapchain);
7418     }
7419     return;
7420 }
7421
7422 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7423     IWineD3DSwapChain *swapchain;
7424
7425     TRACE("Relaying  to swapchain\n");
7426
7427     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
7428         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7429         IWineD3DSwapChain_Release(swapchain);
7430     }
7431     return;
7432 }
7433
7434
7435 /** ********************************************************
7436 *   Notification functions
7437 ** ********************************************************/
7438 /** This function must be called in the release of a resource when ref == 0,
7439 * the contents of resource must still be correct,
7440 * any handles to other resource held by the caller must be closed
7441 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7442  *****************************************************/
7443 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7444     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7445
7446     TRACE("(%p) : Adding Resource %p\n", This, resource);
7447     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
7448 }
7449
7450 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7451     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7452
7453     TRACE("(%p) : Removing resource %p\n", This, resource);
7454
7455     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
7456 }
7457
7458
7459 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7460     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7461     int counter;
7462
7463     TRACE("(%p) : resource %p\n", This, resource);
7464     switch(IWineD3DResource_GetType(resource)){
7465         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
7466         case WINED3DRTYPE_SURFACE: {
7467             unsigned int i;
7468
7469             /* Cleanup any FBO attachments if d3d is enabled */
7470             if(This->d3d_initialized) {
7471                 if((IWineD3DSurface *)resource == This->lastActiveRenderTarget) {
7472                     IWineD3DSwapChainImpl *swapchain = This->swapchains ? (IWineD3DSwapChainImpl *) This->swapchains[0] : NULL;
7473
7474                     TRACE("Last active render target destroyed\n");
7475                     /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
7476                      * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
7477                      * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
7478                      * and the lastActiveRenderTarget member shouldn't matter
7479                      */
7480                     if(swapchain) {
7481                         if(swapchain->backBuffer && swapchain->backBuffer[0] != (IWineD3DSurface *)resource) {
7482                             TRACE("Activating primary back buffer\n");
7483                             ActivateContext(This, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
7484                         } else if(!swapchain->backBuffer && swapchain->frontBuffer != (IWineD3DSurface *)resource) {
7485                             /* Single buffering environment */
7486                             TRACE("Activating primary front buffer\n");
7487                             ActivateContext(This, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD);
7488                         } else {
7489                             TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
7490                             /* Implicit render target destroyed, that means the device is being destroyed
7491                              * whatever we set here, it shouldn't matter
7492                              */
7493                             This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
7494                         }
7495                     } else {
7496                         /* May happen during ddraw uninitialization */
7497                         TRACE("Render target set, but swapchain does not exist!\n");
7498                         This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe;
7499                     }
7500                 }
7501
7502                 ENTER_GL();
7503                 for (i = 0; i < GL_LIMITS(buffers); ++i) {
7504                     if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
7505                         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7506                         set_render_target_fbo(iface, i, NULL);
7507                         This->fbo_color_attachments[i] = NULL;
7508                     }
7509                 }
7510                 if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
7511                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7512                     set_depth_stencil_fbo(iface, NULL);
7513                     This->fbo_depth_attachment = NULL;
7514                 }
7515                 LEAVE_GL();
7516             }
7517
7518             break;
7519         }
7520         case WINED3DRTYPE_TEXTURE:
7521         case WINED3DRTYPE_CUBETEXTURE:
7522         case WINED3DRTYPE_VOLUMETEXTURE:
7523                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
7524                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7525                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7526                         This->stateBlock->textures[counter] = NULL;
7527                     }
7528                     if (This->updateStateBlock != This->stateBlock ){
7529                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7530                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7531                             This->updateStateBlock->textures[counter] = NULL;
7532                         }
7533                     }
7534                 }
7535         break;
7536         case WINED3DRTYPE_VOLUME:
7537         /* TODO: nothing really? */
7538         break;
7539         case WINED3DRTYPE_VERTEXBUFFER:
7540         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7541         {
7542             int streamNumber;
7543             TRACE("Cleaning up stream pointers\n");
7544
7545             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7546                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7547                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7548                 */
7549                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7550                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7551                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7552                         This->updateStateBlock->streamSource[streamNumber] = 0;
7553                         /* Set changed flag? */
7554                     }
7555                 }
7556                 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) */
7557                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7558                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7559                         This->stateBlock->streamSource[streamNumber] = 0;
7560                     }
7561                 }
7562 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7563                  else { /* This shouldn't happen */
7564                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7565                 }
7566 #endif
7567
7568             }
7569         }
7570         break;
7571         case WINED3DRTYPE_INDEXBUFFER:
7572         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7573         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7574             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7575                 This->updateStateBlock->pIndexData =  NULL;
7576             }
7577         }
7578         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7579             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7580                 This->stateBlock->pIndexData =  NULL;
7581             }
7582         }
7583
7584         break;
7585         default:
7586         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7587         break;
7588     }
7589
7590
7591     /* Remove the resource from the resourceStore */
7592     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7593
7594     TRACE("Resource released\n");
7595
7596 }
7597
7598 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
7599     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7600     IWineD3DResourceImpl *resource, *cursor;
7601     HRESULT ret;
7602     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
7603
7604     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
7605         TRACE("enumerating resource %p\n", resource);
7606         IWineD3DResource_AddRef((IWineD3DResource *) resource);
7607         ret = pCallback((IWineD3DResource *) resource, pData);
7608         if(ret == S_FALSE) {
7609             TRACE("Canceling enumeration\n");
7610             break;
7611         }
7612     }
7613     return WINED3D_OK;
7614 }
7615
7616 /**********************************************************
7617  * IWineD3DDevice VTbl follows
7618  **********************************************************/
7619
7620 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7621 {
7622     /*** IUnknown methods ***/
7623     IWineD3DDeviceImpl_QueryInterface,
7624     IWineD3DDeviceImpl_AddRef,
7625     IWineD3DDeviceImpl_Release,
7626     /*** IWineD3DDevice methods ***/
7627     IWineD3DDeviceImpl_GetParent,
7628     /*** Creation methods**/
7629     IWineD3DDeviceImpl_CreateVertexBuffer,
7630     IWineD3DDeviceImpl_CreateIndexBuffer,
7631     IWineD3DDeviceImpl_CreateStateBlock,
7632     IWineD3DDeviceImpl_CreateSurface,
7633     IWineD3DDeviceImpl_CreateTexture,
7634     IWineD3DDeviceImpl_CreateVolumeTexture,
7635     IWineD3DDeviceImpl_CreateVolume,
7636     IWineD3DDeviceImpl_CreateCubeTexture,
7637     IWineD3DDeviceImpl_CreateQuery,
7638     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7639     IWineD3DDeviceImpl_CreateVertexDeclaration,
7640     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7641     IWineD3DDeviceImpl_CreateVertexShader,
7642     IWineD3DDeviceImpl_CreatePixelShader,
7643     IWineD3DDeviceImpl_CreatePalette,
7644     /*** Odd functions **/
7645     IWineD3DDeviceImpl_Init3D,
7646     IWineD3DDeviceImpl_Uninit3D,
7647     IWineD3DDeviceImpl_SetFullscreen,
7648     IWineD3DDeviceImpl_SetMultithreaded,
7649     IWineD3DDeviceImpl_EvictManagedResources,
7650     IWineD3DDeviceImpl_GetAvailableTextureMem,
7651     IWineD3DDeviceImpl_GetBackBuffer,
7652     IWineD3DDeviceImpl_GetCreationParameters,
7653     IWineD3DDeviceImpl_GetDeviceCaps,
7654     IWineD3DDeviceImpl_GetDirect3D,
7655     IWineD3DDeviceImpl_GetDisplayMode,
7656     IWineD3DDeviceImpl_SetDisplayMode,
7657     IWineD3DDeviceImpl_GetHWND,
7658     IWineD3DDeviceImpl_SetHWND,
7659     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7660     IWineD3DDeviceImpl_GetRasterStatus,
7661     IWineD3DDeviceImpl_GetSwapChain,
7662     IWineD3DDeviceImpl_Reset,
7663     IWineD3DDeviceImpl_SetDialogBoxMode,
7664     IWineD3DDeviceImpl_SetCursorProperties,
7665     IWineD3DDeviceImpl_SetCursorPosition,
7666     IWineD3DDeviceImpl_ShowCursor,
7667     IWineD3DDeviceImpl_TestCooperativeLevel,
7668     /*** Getters and setters **/
7669     IWineD3DDeviceImpl_SetClipPlane,
7670     IWineD3DDeviceImpl_GetClipPlane,
7671     IWineD3DDeviceImpl_SetClipStatus,
7672     IWineD3DDeviceImpl_GetClipStatus,
7673     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7674     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7675     IWineD3DDeviceImpl_SetDepthStencilSurface,
7676     IWineD3DDeviceImpl_GetDepthStencilSurface,
7677     IWineD3DDeviceImpl_SetFVF,
7678     IWineD3DDeviceImpl_GetFVF,
7679     IWineD3DDeviceImpl_SetGammaRamp,
7680     IWineD3DDeviceImpl_GetGammaRamp,
7681     IWineD3DDeviceImpl_SetIndices,
7682     IWineD3DDeviceImpl_GetIndices,
7683     IWineD3DDeviceImpl_SetBaseVertexIndex,
7684     IWineD3DDeviceImpl_GetBaseVertexIndex,
7685     IWineD3DDeviceImpl_SetLight,
7686     IWineD3DDeviceImpl_GetLight,
7687     IWineD3DDeviceImpl_SetLightEnable,
7688     IWineD3DDeviceImpl_GetLightEnable,
7689     IWineD3DDeviceImpl_SetMaterial,
7690     IWineD3DDeviceImpl_GetMaterial,
7691     IWineD3DDeviceImpl_SetNPatchMode,
7692     IWineD3DDeviceImpl_GetNPatchMode,
7693     IWineD3DDeviceImpl_SetPaletteEntries,
7694     IWineD3DDeviceImpl_GetPaletteEntries,
7695     IWineD3DDeviceImpl_SetPixelShader,
7696     IWineD3DDeviceImpl_GetPixelShader,
7697     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7698     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7699     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7700     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7701     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7702     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7703     IWineD3DDeviceImpl_SetRenderState,
7704     IWineD3DDeviceImpl_GetRenderState,
7705     IWineD3DDeviceImpl_SetRenderTarget,
7706     IWineD3DDeviceImpl_GetRenderTarget,
7707     IWineD3DDeviceImpl_SetFrontBackBuffers,
7708     IWineD3DDeviceImpl_SetSamplerState,
7709     IWineD3DDeviceImpl_GetSamplerState,
7710     IWineD3DDeviceImpl_SetScissorRect,
7711     IWineD3DDeviceImpl_GetScissorRect,
7712     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7713     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7714     IWineD3DDeviceImpl_SetStreamSource,
7715     IWineD3DDeviceImpl_GetStreamSource,
7716     IWineD3DDeviceImpl_SetStreamSourceFreq,
7717     IWineD3DDeviceImpl_GetStreamSourceFreq,
7718     IWineD3DDeviceImpl_SetTexture,
7719     IWineD3DDeviceImpl_GetTexture,
7720     IWineD3DDeviceImpl_SetTextureStageState,
7721     IWineD3DDeviceImpl_GetTextureStageState,
7722     IWineD3DDeviceImpl_SetTransform,
7723     IWineD3DDeviceImpl_GetTransform,
7724     IWineD3DDeviceImpl_SetVertexDeclaration,
7725     IWineD3DDeviceImpl_GetVertexDeclaration,
7726     IWineD3DDeviceImpl_SetVertexShader,
7727     IWineD3DDeviceImpl_GetVertexShader,
7728     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7729     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7730     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7731     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7732     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7733     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7734     IWineD3DDeviceImpl_SetViewport,
7735     IWineD3DDeviceImpl_GetViewport,
7736     IWineD3DDeviceImpl_MultiplyTransform,
7737     IWineD3DDeviceImpl_ValidateDevice,
7738     IWineD3DDeviceImpl_ProcessVertices,
7739     /*** State block ***/
7740     IWineD3DDeviceImpl_BeginStateBlock,
7741     IWineD3DDeviceImpl_EndStateBlock,
7742     /*** Scene management ***/
7743     IWineD3DDeviceImpl_BeginScene,
7744     IWineD3DDeviceImpl_EndScene,
7745     IWineD3DDeviceImpl_Present,
7746     IWineD3DDeviceImpl_Clear,
7747     /*** Drawing ***/
7748     IWineD3DDeviceImpl_DrawPrimitive,
7749     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7750     IWineD3DDeviceImpl_DrawPrimitiveUP,
7751     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7752     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7753     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7754     IWineD3DDeviceImpl_DrawRectPatch,
7755     IWineD3DDeviceImpl_DrawTriPatch,
7756     IWineD3DDeviceImpl_DeletePatch,
7757     IWineD3DDeviceImpl_ColorFill,
7758     IWineD3DDeviceImpl_UpdateTexture,
7759     IWineD3DDeviceImpl_UpdateSurface,
7760     IWineD3DDeviceImpl_GetFrontBufferData,
7761     /*** object tracking ***/
7762     IWineD3DDeviceImpl_ResourceReleased,
7763     IWineD3DDeviceImpl_EnumResources
7764 };
7765
7766 const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl =
7767 {
7768     /*** IUnknown methods ***/
7769     IWineD3DDeviceImpl_QueryInterface,
7770     IWineD3DDeviceImpl_AddRef,
7771     IWineD3DDeviceImpl_Release,
7772     /*** IWineD3DDevice methods ***/
7773     IWineD3DDeviceImpl_GetParent,
7774     /*** Creation methods**/
7775     IWineD3DDeviceImpl_CreateVertexBuffer,
7776     IWineD3DDeviceImpl_CreateIndexBuffer,
7777     IWineD3DDeviceImpl_CreateStateBlock,
7778     IWineD3DDeviceImpl_CreateSurface,
7779     IWineD3DDeviceImpl_CreateTexture,
7780     IWineD3DDeviceImpl_CreateVolumeTexture,
7781     IWineD3DDeviceImpl_CreateVolume,
7782     IWineD3DDeviceImpl_CreateCubeTexture,
7783     IWineD3DDeviceImpl_CreateQuery,
7784     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7785     IWineD3DDeviceImpl_CreateVertexDeclaration,
7786     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7787     IWineD3DDeviceImpl_CreateVertexShader,
7788     IWineD3DDeviceImpl_CreatePixelShader,
7789     IWineD3DDeviceImpl_CreatePalette,
7790     /*** Odd functions **/
7791     IWineD3DDeviceImpl_Init3D,
7792     IWineD3DDeviceImpl_Uninit3D,
7793     IWineD3DDeviceImpl_SetFullscreen,
7794     IWineD3DDeviceImpl_SetMultithreaded,
7795     IWineD3DDeviceImpl_EvictManagedResources,
7796     IWineD3DDeviceImpl_GetAvailableTextureMem,
7797     IWineD3DDeviceImpl_GetBackBuffer,
7798     IWineD3DDeviceImpl_GetCreationParameters,
7799     IWineD3DDeviceImpl_GetDeviceCaps,
7800     IWineD3DDeviceImpl_GetDirect3D,
7801     IWineD3DDeviceImpl_GetDisplayMode,
7802     IWineD3DDeviceImpl_SetDisplayMode,
7803     IWineD3DDeviceImpl_GetHWND,
7804     IWineD3DDeviceImpl_SetHWND,
7805     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7806     IWineD3DDeviceImpl_GetRasterStatus,
7807     IWineD3DDeviceImpl_GetSwapChain,
7808     IWineD3DDeviceImpl_Reset,
7809     IWineD3DDeviceImpl_SetDialogBoxMode,
7810     IWineD3DDeviceImpl_SetCursorProperties,
7811     IWineD3DDeviceImpl_SetCursorPosition,
7812     IWineD3DDeviceImpl_ShowCursor,
7813     IWineD3DDeviceImpl_TestCooperativeLevel,
7814     /*** Getters and setters **/
7815     IWineD3DDeviceImpl_SetClipPlane,
7816     IWineD3DDeviceImpl_GetClipPlane,
7817     IWineD3DDeviceImpl_SetClipStatus,
7818     IWineD3DDeviceImpl_GetClipStatus,
7819     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7820     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7821     IWineD3DDeviceImpl_SetDepthStencilSurface,
7822     IWineD3DDeviceImpl_GetDepthStencilSurface,
7823     IWineD3DDeviceImpl_SetFVF,
7824     IWineD3DDeviceImpl_GetFVF,
7825     IWineD3DDeviceImpl_SetGammaRamp,
7826     IWineD3DDeviceImpl_GetGammaRamp,
7827     IWineD3DDeviceImpl_SetIndices,
7828     IWineD3DDeviceImpl_GetIndices,
7829     IWineD3DDeviceImpl_SetBaseVertexIndex,
7830     IWineD3DDeviceImpl_GetBaseVertexIndex,
7831     IWineD3DDeviceImpl_SetLight,
7832     IWineD3DDeviceImpl_GetLight,
7833     IWineD3DDeviceImpl_SetLightEnable,
7834     IWineD3DDeviceImpl_GetLightEnable,
7835     IWineD3DDeviceImpl_SetMaterial,
7836     IWineD3DDeviceImpl_GetMaterial,
7837     IWineD3DDeviceImpl_SetNPatchMode,
7838     IWineD3DDeviceImpl_GetNPatchMode,
7839     IWineD3DDeviceImpl_SetPaletteEntries,
7840     IWineD3DDeviceImpl_GetPaletteEntries,
7841     IWineD3DDeviceImpl_SetPixelShader,
7842     IWineD3DDeviceImpl_GetPixelShader,
7843     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7844     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7845     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7846     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7847     IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst,
7848     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7849     IWineD3DDeviceImpl_SetRenderState,
7850     IWineD3DDeviceImpl_GetRenderState,
7851     IWineD3DDeviceImpl_SetRenderTarget,
7852     IWineD3DDeviceImpl_GetRenderTarget,
7853     IWineD3DDeviceImpl_SetFrontBackBuffers,
7854     IWineD3DDeviceImpl_SetSamplerState,
7855     IWineD3DDeviceImpl_GetSamplerState,
7856     IWineD3DDeviceImpl_SetScissorRect,
7857     IWineD3DDeviceImpl_GetScissorRect,
7858     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7859     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7860     IWineD3DDeviceImpl_SetStreamSource,
7861     IWineD3DDeviceImpl_GetStreamSource,
7862     IWineD3DDeviceImpl_SetStreamSourceFreq,
7863     IWineD3DDeviceImpl_GetStreamSourceFreq,
7864     IWineD3DDeviceImpl_SetTexture,
7865     IWineD3DDeviceImpl_GetTexture,
7866     IWineD3DDeviceImpl_SetTextureStageState,
7867     IWineD3DDeviceImpl_GetTextureStageState,
7868     IWineD3DDeviceImpl_SetTransform,
7869     IWineD3DDeviceImpl_GetTransform,
7870     IWineD3DDeviceImpl_SetVertexDeclaration,
7871     IWineD3DDeviceImpl_GetVertexDeclaration,
7872     IWineD3DDeviceImpl_SetVertexShader,
7873     IWineD3DDeviceImpl_GetVertexShader,
7874     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7875     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7876     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7877     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7878     IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst,
7879     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7880     IWineD3DDeviceImpl_SetViewport,
7881     IWineD3DDeviceImpl_GetViewport,
7882     IWineD3DDeviceImpl_MultiplyTransform,
7883     IWineD3DDeviceImpl_ValidateDevice,
7884     IWineD3DDeviceImpl_ProcessVertices,
7885     /*** State block ***/
7886     IWineD3DDeviceImpl_BeginStateBlock,
7887     IWineD3DDeviceImpl_EndStateBlock,
7888     /*** Scene management ***/
7889     IWineD3DDeviceImpl_BeginScene,
7890     IWineD3DDeviceImpl_EndScene,
7891     IWineD3DDeviceImpl_Present,
7892     IWineD3DDeviceImpl_Clear,
7893     /*** Drawing ***/
7894     IWineD3DDeviceImpl_DrawPrimitive,
7895     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7896     IWineD3DDeviceImpl_DrawPrimitiveUP,
7897     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7898     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7899     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7900     IWineD3DDeviceImpl_DrawRectPatch,
7901     IWineD3DDeviceImpl_DrawTriPatch,
7902     IWineD3DDeviceImpl_DeletePatch,
7903     IWineD3DDeviceImpl_ColorFill,
7904     IWineD3DDeviceImpl_UpdateTexture,
7905     IWineD3DDeviceImpl_UpdateSurface,
7906     IWineD3DDeviceImpl_GetFrontBufferData,
7907     /*** object tracking ***/
7908     IWineD3DDeviceImpl_ResourceReleased,
7909     IWineD3DDeviceImpl_EnumResources
7910 };
7911
7912 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7913     WINED3DRS_ALPHABLENDENABLE   ,
7914     WINED3DRS_ALPHAFUNC          ,
7915     WINED3DRS_ALPHAREF           ,
7916     WINED3DRS_ALPHATESTENABLE    ,
7917     WINED3DRS_BLENDOP            ,
7918     WINED3DRS_COLORWRITEENABLE   ,
7919     WINED3DRS_DESTBLEND          ,
7920     WINED3DRS_DITHERENABLE       ,
7921     WINED3DRS_FILLMODE           ,
7922     WINED3DRS_FOGDENSITY         ,
7923     WINED3DRS_FOGEND             ,
7924     WINED3DRS_FOGSTART           ,
7925     WINED3DRS_LASTPIXEL          ,
7926     WINED3DRS_SHADEMODE          ,
7927     WINED3DRS_SRCBLEND           ,
7928     WINED3DRS_STENCILENABLE      ,
7929     WINED3DRS_STENCILFAIL        ,
7930     WINED3DRS_STENCILFUNC        ,
7931     WINED3DRS_STENCILMASK        ,
7932     WINED3DRS_STENCILPASS        ,
7933     WINED3DRS_STENCILREF         ,
7934     WINED3DRS_STENCILWRITEMASK   ,
7935     WINED3DRS_STENCILZFAIL       ,
7936     WINED3DRS_TEXTUREFACTOR      ,
7937     WINED3DRS_WRAP0              ,
7938     WINED3DRS_WRAP1              ,
7939     WINED3DRS_WRAP2              ,
7940     WINED3DRS_WRAP3              ,
7941     WINED3DRS_WRAP4              ,
7942     WINED3DRS_WRAP5              ,
7943     WINED3DRS_WRAP6              ,
7944     WINED3DRS_WRAP7              ,
7945     WINED3DRS_ZENABLE            ,
7946     WINED3DRS_ZFUNC              ,
7947     WINED3DRS_ZWRITEENABLE
7948 };
7949
7950 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7951     WINED3DTSS_ADDRESSW              ,
7952     WINED3DTSS_ALPHAARG0             ,
7953     WINED3DTSS_ALPHAARG1             ,
7954     WINED3DTSS_ALPHAARG2             ,
7955     WINED3DTSS_ALPHAOP               ,
7956     WINED3DTSS_BUMPENVLOFFSET        ,
7957     WINED3DTSS_BUMPENVLSCALE         ,
7958     WINED3DTSS_BUMPENVMAT00          ,
7959     WINED3DTSS_BUMPENVMAT01          ,
7960     WINED3DTSS_BUMPENVMAT10          ,
7961     WINED3DTSS_BUMPENVMAT11          ,
7962     WINED3DTSS_COLORARG0             ,
7963     WINED3DTSS_COLORARG1             ,
7964     WINED3DTSS_COLORARG2             ,
7965     WINED3DTSS_COLOROP               ,
7966     WINED3DTSS_RESULTARG             ,
7967     WINED3DTSS_TEXCOORDINDEX         ,
7968     WINED3DTSS_TEXTURETRANSFORMFLAGS
7969 };
7970
7971 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7972     WINED3DSAMP_ADDRESSU         ,
7973     WINED3DSAMP_ADDRESSV         ,
7974     WINED3DSAMP_ADDRESSW         ,
7975     WINED3DSAMP_BORDERCOLOR      ,
7976     WINED3DSAMP_MAGFILTER        ,
7977     WINED3DSAMP_MINFILTER        ,
7978     WINED3DSAMP_MIPFILTER        ,
7979     WINED3DSAMP_MIPMAPLODBIAS    ,
7980     WINED3DSAMP_MAXMIPLEVEL      ,
7981     WINED3DSAMP_MAXANISOTROPY    ,
7982     WINED3DSAMP_SRGBTEXTURE      ,
7983     WINED3DSAMP_ELEMENTINDEX
7984 };
7985
7986 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7987     WINED3DRS_AMBIENT                       ,
7988     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7989     WINED3DRS_CLIPPING                      ,
7990     WINED3DRS_CLIPPLANEENABLE               ,
7991     WINED3DRS_COLORVERTEX                   ,
7992     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7993     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7994     WINED3DRS_FOGDENSITY                    ,
7995     WINED3DRS_FOGEND                        ,
7996     WINED3DRS_FOGSTART                      ,
7997     WINED3DRS_FOGTABLEMODE                  ,
7998     WINED3DRS_FOGVERTEXMODE                 ,
7999     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
8000     WINED3DRS_LIGHTING                      ,
8001     WINED3DRS_LOCALVIEWER                   ,
8002     WINED3DRS_MULTISAMPLEANTIALIAS          ,
8003     WINED3DRS_MULTISAMPLEMASK               ,
8004     WINED3DRS_NORMALIZENORMALS              ,
8005     WINED3DRS_PATCHEDGESTYLE                ,
8006     WINED3DRS_POINTSCALE_A                  ,
8007     WINED3DRS_POINTSCALE_B                  ,
8008     WINED3DRS_POINTSCALE_C                  ,
8009     WINED3DRS_POINTSCALEENABLE              ,
8010     WINED3DRS_POINTSIZE                     ,
8011     WINED3DRS_POINTSIZE_MAX                 ,
8012     WINED3DRS_POINTSIZE_MIN                 ,
8013     WINED3DRS_POINTSPRITEENABLE             ,
8014     WINED3DRS_RANGEFOGENABLE                ,
8015     WINED3DRS_SPECULARMATERIALSOURCE        ,
8016     WINED3DRS_TWEENFACTOR                   ,
8017     WINED3DRS_VERTEXBLEND                   ,
8018     WINED3DRS_CULLMODE                      ,
8019     WINED3DRS_FOGCOLOR
8020 };
8021
8022 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8023     WINED3DTSS_TEXCOORDINDEX         ,
8024     WINED3DTSS_TEXTURETRANSFORMFLAGS
8025 };
8026
8027 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8028     WINED3DSAMP_DMAPOFFSET
8029 };
8030
8031 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
8032     DWORD rep = This->StateTable[state].representative;
8033     DWORD idx;
8034     BYTE shift;
8035     UINT i;
8036     WineD3DContext *context;
8037
8038     if(!rep) return;
8039     for(i = 0; i < This->numContexts; i++) {
8040         context = This->contexts[i];
8041         if(isStateDirty(context, rep)) continue;
8042
8043         context->dirtyArray[context->numDirtyEntries++] = rep;
8044         idx = rep >> 5;
8045         shift = rep & 0x1f;
8046         context->isStateDirty[idx] |= (1 << shift);
8047     }
8048 }
8049
8050 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
8051     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
8052     /* The drawable size of a pbuffer render target is the current pbuffer size
8053      */
8054     *width = dev->pbufferWidth;
8055     *height = dev->pbufferHeight;
8056 }
8057
8058 void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
8059     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
8060      */
8061     *width = This->pow2Width;
8062     *height = This->pow2Height;
8063 }
8064
8065 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
8066     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
8067     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
8068      * current context's drawable, which is the size of the back buffer of the swapchain
8069      * the active context belongs to. The back buffer of the swapchain is stored as the
8070      * surface the context belongs to.
8071      */
8072     *width = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Width;
8073     *height = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Height;
8074 }