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