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