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