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