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