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