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