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