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