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