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