mshtml: Added IHTMLStyleSheet::get_rules implementation.
[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(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4820                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4821                This->stateBlock->scissorRect.right < target->currentDesc.Width ||
4822                This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) {
4823                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4824                 break;
4825             }
4826             if(Count > 0 && pRects && (
4827                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4828                pRects[0].x2 < target->currentDesc.Width ||
4829                pRects[0].y2 < target->currentDesc.Height)) {
4830                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4831                 break;
4832             }
4833             break;
4834         }
4835     }
4836
4837     target->get_drawable_size(target, &drawable_width, &drawable_height);
4838
4839     /* This is for offscreen rendering as well as for multithreading, thus activate the set render target
4840      * and not the last active one.
4841      */
4842     ActivateContext(This, This->render_targets[0], CTXUSAGE_CLEAR);
4843     ENTER_GL();
4844
4845     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4846         apply_fbo_state(iface);
4847     }
4848
4849     /* Only set the values up once, as they are not changing */
4850     if (Flags & WINED3DCLEAR_STENCIL) {
4851         glClearStencil(Stencil);
4852         checkGLcall("glClearStencil");
4853         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4854         glStencilMask(0xFFFFFFFF);
4855     }
4856
4857     if (Flags & WINED3DCLEAR_ZBUFFER) {
4858         glDepthMask(GL_TRUE);
4859         glClearDepth(Z);
4860         checkGLcall("glClearDepth");
4861         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4862         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4863     }
4864
4865     if (Flags & WINED3DCLEAR_TARGET) {
4866         TRACE("Clearing screen with glClear to color %x\n", Color);
4867         glClearColor(D3DCOLOR_R(Color),
4868                      D3DCOLOR_G(Color),
4869                      D3DCOLOR_B(Color),
4870                      D3DCOLOR_A(Color));
4871         checkGLcall("glClearColor");
4872
4873         /* Clear ALL colors! */
4874         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4875         glMask = glMask | GL_COLOR_BUFFER_BIT;
4876     }
4877
4878     vp_rect.left = vp->X;
4879     vp_rect.top = vp->Y;
4880     vp_rect.right = vp->X + vp->Width;
4881     vp_rect.bottom = vp->Y + vp->Height;
4882     if (!(Count > 0 && pRects)) {
4883         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4884             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
4885         }
4886         if(This->render_offscreen) {
4887             glScissor(vp_rect.left, vp_rect.top,
4888                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4889         } else {
4890             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
4891                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4892         }
4893         checkGLcall("glScissor");
4894         glClear(glMask);
4895         checkGLcall("glClear");
4896     } else {
4897         /* Now process each rect in turn */
4898         for (i = 0; i < Count; i++) {
4899             /* Note gl uses lower left, width/height */
4900             IntersectRect((RECT *) &curRect, &vp_rect, (RECT *) &pRects[i]);
4901             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4902                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
4903             }
4904             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
4905                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
4906                   curRect.x1, (target->currentDesc.Height - curRect.y2),
4907                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4908
4909             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4910              * The rectangle is not cleared, no error is returned, but further rectanlges are
4911              * still cleared if they are valid
4912              */
4913             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
4914                 TRACE("Rectangle with negative dimensions, ignoring\n");
4915                 continue;
4916             }
4917
4918             if(This->render_offscreen) {
4919                 glScissor(curRect.x1, curRect.y1,
4920                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4921             } else {
4922                 glScissor(curRect.x1, drawable_height - curRect.y2,
4923                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4924             }
4925             checkGLcall("glScissor");
4926
4927             glClear(glMask);
4928             checkGLcall("glClear");
4929         }
4930     }
4931
4932     /* Restore the old values (why..?) */
4933     if (Flags & WINED3DCLEAR_STENCIL) {
4934         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4935     }
4936     if (Flags & WINED3DCLEAR_TARGET) {
4937         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4938         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4939                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4940                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4941                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4942
4943         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
4944          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
4945          */
4946         IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE);
4947         /* TODO: Move the fbo logic into ModifyLocation() */
4948         if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4949             target->Flags |= SFLAG_INTEXTURE;
4950         }
4951     }
4952     LEAVE_GL();
4953
4954     return WINED3D_OK;
4955 }
4956
4957 /*****
4958  * Drawing functions
4959  *****/
4960 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4961                                                 UINT PrimitiveCount) {
4962
4963     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4964
4965     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4966                                debug_d3dprimitivetype(PrimitiveType),
4967                                StartVertex, PrimitiveCount);
4968
4969     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4970     if(This->stateBlock->streamIsUP) {
4971         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4972         This->stateBlock->streamIsUP = FALSE;
4973     }
4974
4975     if(This->stateBlock->loadBaseVertexIndex != 0) {
4976         This->stateBlock->loadBaseVertexIndex = 0;
4977         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4978     }
4979     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4980     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4981                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4982     return WINED3D_OK;
4983 }
4984
4985 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4986 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4987                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4988                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4989
4990     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4991     UINT                 idxStride = 2;
4992     IWineD3DIndexBuffer *pIB;
4993     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4994     GLuint vbo;
4995
4996     pIB = This->stateBlock->pIndexData;
4997     if (!pIB) {
4998         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4999          * without an index buffer set. (The first time at least...)
5000          * D3D8 simply dies, but I doubt it can do much harm to return
5001          * D3DERR_INVALIDCALL there as well. */
5002         ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
5003         return WINED3DERR_INVALIDCALL;
5004     }
5005
5006     if(This->stateBlock->streamIsUP) {
5007         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5008         This->stateBlock->streamIsUP = FALSE;
5009     }
5010     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
5011
5012     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
5013           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5014           minIndex, NumVertices, startIndex, primCount);
5015
5016     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5017     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5018         idxStride = 2;
5019     } else {
5020         idxStride = 4;
5021     }
5022
5023     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
5024         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
5025         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5026     }
5027
5028     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
5029                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5030
5031     return WINED3D_OK;
5032 }
5033
5034 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5035                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5036                                                     UINT VertexStreamZeroStride) {
5037     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5038     IWineD3DVertexBuffer *vb;
5039
5040     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5041              debug_d3dprimitivetype(PrimitiveType),
5042              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5043
5044     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5045     vb = This->stateBlock->streamSource[0];
5046     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5047     if(vb) IWineD3DVertexBuffer_Release(vb);
5048     This->stateBlock->streamOffset[0] = 0;
5049     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5050     This->stateBlock->streamIsUP = TRUE;
5051     This->stateBlock->loadBaseVertexIndex = 0;
5052
5053     /* TODO: Only mark dirty if drawing from a different UP address */
5054     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5055
5056     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
5057                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5058
5059     /* MSDN specifies stream zero settings must be set to NULL */
5060     This->stateBlock->streamStride[0] = 0;
5061     This->stateBlock->streamSource[0] = NULL;
5062
5063     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5064      * the new stream sources or use UP drawing again
5065      */
5066     return WINED3D_OK;
5067 }
5068
5069 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5070                                                              UINT MinVertexIndex, UINT NumVertices,
5071                                                              UINT PrimitiveCount, CONST void* pIndexData,
5072                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5073                                                              UINT VertexStreamZeroStride) {
5074     int                 idxStride;
5075     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5076     IWineD3DVertexBuffer *vb;
5077     IWineD3DIndexBuffer *ib;
5078
5079     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5080              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5081              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5082              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5083
5084     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5085         idxStride = 2;
5086     } else {
5087         idxStride = 4;
5088     }
5089
5090     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5091     vb = This->stateBlock->streamSource[0];
5092     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5093     if(vb) IWineD3DVertexBuffer_Release(vb);
5094     This->stateBlock->streamIsUP = TRUE;
5095     This->stateBlock->streamOffset[0] = 0;
5096     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5097
5098     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5099     This->stateBlock->baseVertexIndex = 0;
5100     This->stateBlock->loadBaseVertexIndex = 0;
5101     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5102     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5103     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5104
5105     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5106
5107     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5108     This->stateBlock->streamSource[0] = NULL;
5109     This->stateBlock->streamStride[0] = 0;
5110     ib = This->stateBlock->pIndexData;
5111     if(ib) {
5112         IWineD3DIndexBuffer_Release(ib);
5113         This->stateBlock->pIndexData = NULL;
5114     }
5115     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5116      * SetStreamSource to specify a vertex buffer
5117      */
5118
5119     return WINED3D_OK;
5120 }
5121
5122 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5124
5125     /* Mark the state dirty until we have nicer tracking
5126      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5127      * that value.
5128      */
5129     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5130     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5131     This->stateBlock->baseVertexIndex = 0;
5132     This->up_strided = DrawPrimStrideData;
5133     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
5134     This->up_strided = NULL;
5135     return WINED3D_OK;
5136 }
5137
5138 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData, UINT NumVertices, CONST void *pIndexData, WINED3DFORMAT IndexDataFormat) {
5139     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5140     DWORD idxSize = (IndexDataFormat == WINED3DFMT_INDEX32 ? 4 : 2);
5141
5142     /* Mark the state dirty until we have nicer tracking
5143      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5144      * that value.
5145      */
5146     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5147     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5148     This->stateBlock->streamIsUP = TRUE;
5149     This->stateBlock->baseVertexIndex = 0;
5150     This->up_strided = DrawPrimStrideData;
5151     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
5152     This->up_strided = NULL;
5153     return WINED3D_OK;
5154 }
5155
5156 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
5157     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5158      * not callable by the app directly no parameter validation checks are needed here.
5159      */
5160     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5161     WINED3DLOCKED_BOX src;
5162     WINED3DLOCKED_BOX dst;
5163     HRESULT hr;
5164     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
5165
5166     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5167      * dirtification to improve loading performance.
5168      */
5169     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
5170     if(FAILED(hr)) return hr;
5171     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
5172     if(FAILED(hr)) {
5173     IWineD3DVolume_UnlockBox(pSourceVolume);
5174             return hr;
5175     }
5176
5177     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
5178
5179     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
5180     if(FAILED(hr)) {
5181         IWineD3DVolume_UnlockBox(pSourceVolume);
5182     } else {
5183         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
5184     }
5185     return hr;
5186 }
5187
5188 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5189 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5190     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5191     HRESULT hr = WINED3D_OK;
5192     WINED3DRESOURCETYPE sourceType;
5193     WINED3DRESOURCETYPE destinationType;
5194     int i ,levels;
5195
5196     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5197
5198     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5199
5200     /* verify that the source and destination textures aren't NULL */
5201     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5202         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5203              This, pSourceTexture, pDestinationTexture);
5204         hr = WINED3DERR_INVALIDCALL;
5205     }
5206
5207     if (pSourceTexture == pDestinationTexture) {
5208         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5209              This, pSourceTexture, pDestinationTexture);
5210         hr = WINED3DERR_INVALIDCALL;
5211     }
5212     /* Verify that the source and destination textures are the same type */
5213     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5214     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5215
5216     if (sourceType != destinationType) {
5217         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5218              This);
5219         hr = WINED3DERR_INVALIDCALL;
5220     }
5221
5222     /* check that both textures have the identical numbers of levels  */
5223     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5224         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5225         hr = WINED3DERR_INVALIDCALL;
5226     }
5227
5228     if (WINED3D_OK == hr) {
5229
5230         /* Make sure that the destination texture is loaded */
5231         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5232
5233         /* Update every surface level of the texture */
5234         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5235
5236         switch (sourceType) {
5237         case WINED3DRTYPE_TEXTURE:
5238             {
5239                 IWineD3DSurface *srcSurface;
5240                 IWineD3DSurface *destSurface;
5241
5242                 for (i = 0 ; i < levels ; ++i) {
5243                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5244                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5245                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5246                     IWineD3DSurface_Release(srcSurface);
5247                     IWineD3DSurface_Release(destSurface);
5248                     if (WINED3D_OK != hr) {
5249                         WARN("(%p) : Call to update surface failed\n", This);
5250                         return hr;
5251                     }
5252                 }
5253             }
5254             break;
5255         case WINED3DRTYPE_CUBETEXTURE:
5256             {
5257                 IWineD3DSurface *srcSurface;
5258                 IWineD3DSurface *destSurface;
5259                 WINED3DCUBEMAP_FACES faceType;
5260
5261                 for (i = 0 ; i < levels ; ++i) {
5262                     /* Update each cube face */
5263                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5264                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5265                         if (WINED3D_OK != hr) {
5266                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5267                         } else {
5268                             TRACE("Got srcSurface %p\n", srcSurface);
5269                         }
5270                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5271                         if (WINED3D_OK != hr) {
5272                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5273                         } else {
5274                             TRACE("Got desrSurface %p\n", destSurface);
5275                         }
5276                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5277                         IWineD3DSurface_Release(srcSurface);
5278                         IWineD3DSurface_Release(destSurface);
5279                         if (WINED3D_OK != hr) {
5280                             WARN("(%p) : Call to update surface failed\n", This);
5281                             return hr;
5282                         }
5283                     }
5284                 }
5285             }
5286             break;
5287
5288         case WINED3DRTYPE_VOLUMETEXTURE:
5289             {
5290                 IWineD3DVolume  *srcVolume  = NULL;
5291                 IWineD3DVolume  *destVolume = NULL;
5292
5293                 for (i = 0 ; i < levels ; ++i) {
5294                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5295                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5296                     hr =  IWineD3DDeviceImpl_UpdateVolume(iface, srcVolume, destVolume);
5297                     IWineD3DVolume_Release(srcVolume);
5298                     IWineD3DVolume_Release(destVolume);
5299                     if (WINED3D_OK != hr) {
5300                         WARN("(%p) : Call to update volume failed\n", This);
5301                         return hr;
5302                     }
5303                 }
5304             }
5305             break;
5306
5307         default:
5308             FIXME("(%p) : Unsupported source and destination type\n", This);
5309             hr = WINED3DERR_INVALIDCALL;
5310         }
5311     }
5312
5313     return hr;
5314 }
5315
5316 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5317     IWineD3DSwapChain *swapChain;
5318     HRESULT hr;
5319     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5320     if(hr == WINED3D_OK) {
5321         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5322                 IWineD3DSwapChain_Release(swapChain);
5323     }
5324     return hr;
5325 }
5326
5327 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5328     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5329     /* return a sensible default */
5330     *pNumPasses = 1;
5331     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5332     FIXME("(%p) : stub\n", This);
5333     return WINED3D_OK;
5334 }
5335
5336 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5337     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5338     int j;
5339     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5340     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5341         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5342         return WINED3DERR_INVALIDCALL;
5343     }
5344     for (j = 0; j < 256; ++j) {
5345         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5346         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5347         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5348         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5349     }
5350     TRACE("(%p) : returning\n", This);
5351     return WINED3D_OK;
5352 }
5353
5354 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5355     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5356     int j;
5357     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5358     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5359         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5360         return WINED3DERR_INVALIDCALL;
5361     }
5362     for (j = 0; j < 256; ++j) {
5363         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5364         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5365         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5366         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5367     }
5368     TRACE("(%p) : returning\n", This);
5369     return WINED3D_OK;
5370 }
5371
5372 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5373     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5374     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5375     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5376         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5377         return WINED3DERR_INVALIDCALL;
5378     }
5379     /*TODO: stateblocks */
5380     This->currentPalette = PaletteNumber;
5381     TRACE("(%p) : returning\n", This);
5382     return WINED3D_OK;
5383 }
5384
5385 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5387     if (PaletteNumber == NULL) {
5388         WARN("(%p) : returning Invalid Call\n", This);
5389         return WINED3DERR_INVALIDCALL;
5390     }
5391     /*TODO: stateblocks */
5392     *PaletteNumber = This->currentPalette;
5393     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5394     return WINED3D_OK;
5395 }
5396
5397 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5398     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5399     static BOOL showFixmes = TRUE;
5400     if (showFixmes) {
5401         FIXME("(%p) : stub\n", This);
5402         showFixmes = FALSE;
5403     }
5404
5405     This->softwareVertexProcessing = bSoftware;
5406     return WINED3D_OK;
5407 }
5408
5409
5410 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5411     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5412     static BOOL showFixmes = TRUE;
5413     if (showFixmes) {
5414         FIXME("(%p) : stub\n", This);
5415         showFixmes = FALSE;
5416     }
5417     return This->softwareVertexProcessing;
5418 }
5419
5420
5421 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5422     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5423     IWineD3DSwapChain *swapChain;
5424     HRESULT hr;
5425
5426     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5427
5428     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5429     if(hr == WINED3D_OK){
5430         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5431         IWineD3DSwapChain_Release(swapChain);
5432     }else{
5433         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5434     }
5435     return hr;
5436 }
5437
5438
5439 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5440     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5441     static BOOL showfixmes = TRUE;
5442     if(nSegments != 0.0f) {
5443         if( showfixmes) {
5444             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5445             showfixmes = FALSE;
5446         }
5447     }
5448     return WINED3D_OK;
5449 }
5450
5451 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5452     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5453     static BOOL showfixmes = TRUE;
5454     if( showfixmes) {
5455         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5456         showfixmes = FALSE;
5457     }
5458     return 0.0f;
5459 }
5460
5461 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5462     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5463     /** TODO: remove casts to IWineD3DSurfaceImpl
5464      *       NOTE: move code to surface to accomplish this
5465       ****************************************/
5466     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5467     int srcWidth, srcHeight;
5468     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5469     WINED3DFORMAT destFormat, srcFormat;
5470     UINT          destSize;
5471     int srcLeft, destLeft, destTop;
5472     WINED3DPOOL       srcPool, destPool;
5473     int offset    = 0;
5474     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5475     glDescriptor *glDescription = NULL;
5476     GLenum dummy;
5477     int bpp;
5478     CONVERT_TYPES convert = NO_CONVERSION;
5479
5480     WINED3DSURFACE_DESC  winedesc;
5481
5482     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5483     memset(&winedesc, 0, sizeof(winedesc));
5484     winedesc.Width  = &srcSurfaceWidth;
5485     winedesc.Height = &srcSurfaceHeight;
5486     winedesc.Pool   = &srcPool;
5487     winedesc.Format = &srcFormat;
5488
5489     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5490
5491     winedesc.Width  = &destSurfaceWidth;
5492     winedesc.Height = &destSurfaceHeight;
5493     winedesc.Pool   = &destPool;
5494     winedesc.Format = &destFormat;
5495     winedesc.Size   = &destSize;
5496
5497     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5498
5499     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5500         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5501         return WINED3DERR_INVALIDCALL;
5502     }
5503
5504     /* This call loads the opengl surface directly, instead of copying the surface to the
5505      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5506      * copy in sysmem and use regular surface loading.
5507      */
5508     d3dfmt_get_conv((IWineD3DSurfaceImpl *) pDestinationSurface, FALSE, TRUE,
5509                     &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5510     if(convert != NO_CONVERSION) {
5511         return IWineD3DSurface_BltFast(pDestinationSurface,
5512                                         pDestPoint  ? pDestPoint->x : 0,
5513                                         pDestPoint  ? pDestPoint->y : 0,
5514                                         pSourceSurface, (RECT *) pSourceRect, 0);
5515     }
5516
5517     if (destFormat == WINED3DFMT_UNKNOWN) {
5518         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5519         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5520
5521         /* Get the update surface description */
5522         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5523     }
5524
5525     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5526
5527     ENTER_GL();
5528
5529     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5530         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5531         checkGLcall("glActiveTextureARB");
5532     }
5533
5534     /* Make sure the surface is loaded and up to date */
5535     IWineD3DSurface_PreLoad(pDestinationSurface);
5536
5537     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5538
5539     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5540     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5541     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5542     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5543     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5544     destTop    = pDestPoint  ? pDestPoint->y : 0;
5545
5546
5547     /* This function doesn't support compressed textures
5548     the pitch is just bytesPerPixel * width */
5549     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5550         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5551         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5552         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5553     }
5554     /* TODO DXT formats */
5555
5556     if(pSourceRect != NULL && pSourceRect->top != 0){
5557        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5558     }
5559     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5560     ,This
5561     ,glDescription->level
5562     ,destLeft
5563     ,destTop
5564     ,srcWidth
5565     ,srcHeight
5566     ,glDescription->glFormat
5567     ,glDescription->glType
5568     ,IWineD3DSurface_GetData(pSourceSurface)
5569     );
5570
5571     /* Sanity check */
5572     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5573
5574         /* need to lock the surface to get the data */
5575         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5576     }
5577
5578     /* TODO: Cube and volume support */
5579     if(rowoffset != 0){
5580         /* not a whole row so we have to do it a line at a time */
5581         int j;
5582
5583         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5584         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5585
5586         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5587
5588                 glTexSubImage2D(glDescription->target
5589                     ,glDescription->level
5590                     ,destLeft
5591                     ,j
5592                     ,srcWidth
5593                     ,1
5594                     ,glDescription->glFormat
5595                     ,glDescription->glType
5596                     ,data /* could be quicker using */
5597                 );
5598             data += rowoffset;
5599         }
5600
5601     } else { /* Full width, so just write out the whole texture */
5602
5603         if (WINED3DFMT_DXT1 == destFormat ||
5604             WINED3DFMT_DXT2 == destFormat ||
5605             WINED3DFMT_DXT3 == destFormat ||
5606             WINED3DFMT_DXT4 == destFormat ||
5607             WINED3DFMT_DXT5 == destFormat) {
5608             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5609                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5610                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5611                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5612                 } if (destFormat != srcFormat) {
5613                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5614                 } else {
5615                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5616                                                         glDescription->level,
5617                                                         glDescription->glFormatInternal,
5618                                                         srcWidth,
5619                                                         srcHeight,
5620                                                         0,
5621                                                         destSize,
5622                                                         IWineD3DSurface_GetData(pSourceSurface));
5623                 }
5624             } else {
5625                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5626             }
5627
5628
5629         } else {
5630             glTexSubImage2D(glDescription->target
5631                     ,glDescription->level
5632                     ,destLeft
5633                     ,destTop
5634                     ,srcWidth
5635                     ,srcHeight
5636                     ,glDescription->glFormat
5637                     ,glDescription->glType
5638                     ,IWineD3DSurface_GetData(pSourceSurface)
5639                 );
5640         }
5641      }
5642     checkGLcall("glTexSubImage2D");
5643
5644     LEAVE_GL();
5645
5646     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5647     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5648
5649     return WINED3D_OK;
5650 }
5651
5652 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5653     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5654     struct WineD3DRectPatch *patch;
5655     unsigned int i;
5656     struct list *e;
5657     BOOL found;
5658     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5659
5660     if(!(Handle || pRectPatchInfo)) {
5661         /* TODO: Write a test for the return value, thus the FIXME */
5662         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5663         return WINED3DERR_INVALIDCALL;
5664     }
5665
5666     if(Handle) {
5667         i = PATCHMAP_HASHFUNC(Handle);
5668         found = FALSE;
5669         LIST_FOR_EACH(e, &This->patches[i]) {
5670             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5671             if(patch->Handle == Handle) {
5672                 found = TRUE;
5673                 break;
5674             }
5675         }
5676
5677         if(!found) {
5678             TRACE("Patch does not exist. Creating a new one\n");
5679             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5680             patch->Handle = Handle;
5681             list_add_head(&This->patches[i], &patch->entry);
5682         } else {
5683             TRACE("Found existing patch %p\n", patch);
5684         }
5685     } else {
5686         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5687          * attributes we have to tesselate, read back, and draw. This needs a patch
5688          * management structure instance. Create one.
5689          *
5690          * A possible improvement is to check if a vertex shader is used, and if not directly
5691          * draw the patch.
5692          */
5693         FIXME("Drawing an uncached patch. This is slow\n");
5694         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5695     }
5696
5697     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5698        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5699        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5700         HRESULT hr;
5701         TRACE("Tesselation density or patch info changed, retesselating\n");
5702
5703         if(pRectPatchInfo) {
5704             memcpy(&patch->RectPatchInfo, pRectPatchInfo, sizeof(*pRectPatchInfo));
5705         }
5706         patch->numSegs[0] = pNumSegs[0];
5707         patch->numSegs[1] = pNumSegs[1];
5708         patch->numSegs[2] = pNumSegs[2];
5709         patch->numSegs[3] = pNumSegs[3];
5710
5711         hr = tesselate_rectpatch(This, patch);
5712         if(FAILED(hr)) {
5713             WARN("Patch tesselation failed\n");
5714
5715             /* Do not release the handle to store the params of the patch */
5716             if(!Handle) {
5717                 HeapFree(GetProcessHeap(), 0, patch);
5718             }
5719             return hr;
5720         }
5721     }
5722
5723     This->currentPatch = patch;
5724     IWineD3DDevice_DrawPrimitiveStrided(iface, WINED3DPT_TRIANGLELIST, patch->numSegs[0] * patch->numSegs[1] * 2, &patch->strided);
5725     This->currentPatch = NULL;
5726
5727     /* Destroy uncached patches */
5728     if(!Handle) {
5729         HeapFree(GetProcessHeap(), 0, patch->mem);
5730         HeapFree(GetProcessHeap(), 0, patch);
5731     }
5732     return WINED3D_OK;
5733 }
5734
5735 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5736 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5737     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5738     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5739     FIXME("(%p) : Stub\n", This);
5740     return WINED3D_OK;
5741 }
5742
5743 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5744     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5745     int i;
5746     struct WineD3DRectPatch *patch;
5747     struct list *e;
5748     TRACE("(%p) Handle(%d)\n", This, Handle);
5749
5750     i = PATCHMAP_HASHFUNC(Handle);
5751     LIST_FOR_EACH(e, &This->patches[i]) {
5752         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5753         if(patch->Handle == Handle) {
5754             TRACE("Deleting patch %p\n", patch);
5755             list_remove(&patch->entry);
5756             HeapFree(GetProcessHeap(), 0, patch->mem);
5757             HeapFree(GetProcessHeap(), 0, patch);
5758             return WINED3D_OK;
5759         }
5760     }
5761
5762     /* TODO: Write a test for the return value */
5763     FIXME("Attempt to destroy nonexistant patch\n");
5764     return WINED3DERR_INVALIDCALL;
5765 }
5766
5767 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
5768     HRESULT hr;
5769     IWineD3DSwapChain *swapchain;
5770
5771     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
5772     if (SUCCEEDED(hr)) {
5773         IWineD3DSwapChain_Release((IUnknown *)swapchain);
5774         return swapchain;
5775     }
5776
5777     return NULL;
5778 }
5779
5780 static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
5781     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5782
5783     if (!*fbo) {
5784         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
5785         checkGLcall("glGenFramebuffersEXT()");
5786     }
5787     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
5788     checkGLcall("glBindFramebuffer()");
5789 }
5790
5791 static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
5792     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
5793     IWineD3DBaseTextureImpl *texture_impl;
5794     GLenum texttarget, target;
5795     GLint old_binding;
5796
5797     texttarget = surface_impl->glDescription.target;
5798     if(texttarget == GL_TEXTURE_2D) {
5799         target = GL_TEXTURE_2D;
5800         glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
5801     } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
5802         target = GL_TEXTURE_RECTANGLE_ARB;
5803         glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
5804     } else {
5805         target = GL_TEXTURE_CUBE_MAP_ARB;
5806         glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5807     }
5808
5809     IWineD3DSurface_PreLoad(surface);
5810
5811     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5812     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5813     glBindTexture(target, old_binding);
5814
5815     /* Update base texture states array */
5816     if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
5817         texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
5818         texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
5819         if (texture_impl->baseTexture.bindCount) {
5820             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
5821         }
5822
5823         IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
5824     }
5825
5826     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget,
5827             surface_impl->glDescription.textureName, surface_impl->glDescription.level));
5828
5829     checkGLcall("attach_surface_fbo");
5830 }
5831
5832 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
5833     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5834     IWineD3DSwapChain *swapchain;
5835
5836     swapchain = get_swapchain(surface);
5837     if (swapchain) {
5838         GLenum buffer;
5839
5840         TRACE("Surface %p is onscreen\n", surface);
5841
5842         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5843         buffer = surface_get_gl_buffer(surface, swapchain);
5844         glDrawBuffer(buffer);
5845         checkGLcall("glDrawBuffer()");
5846     } else {
5847         TRACE("Surface %p is offscreen\n", surface);
5848         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
5849         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
5850     }
5851
5852     if (rect) {
5853         glEnable(GL_SCISSOR_TEST);
5854         if(!swapchain) {
5855             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
5856         } else {
5857             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
5858                     rect->x2 - rect->x1, rect->y2 - rect->y1);
5859         }
5860         checkGLcall("glScissor");
5861     } else {
5862         glDisable(GL_SCISSOR_TEST);
5863     }
5864     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5865
5866     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5867     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
5868
5869     glClearColor(D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color));
5870     glClear(GL_COLOR_BUFFER_BIT);
5871     checkGLcall("glClear");
5872
5873     if (This->render_offscreen) {
5874         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5875     } else {
5876         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5877         checkGLcall("glBindFramebuffer()");
5878     }
5879
5880     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
5881             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
5882         glDrawBuffer(GL_BACK);
5883         checkGLcall("glDrawBuffer()");
5884     }
5885 }
5886
5887 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
5888     unsigned int r, g, b, a;
5889     DWORD ret;
5890
5891     if(destfmt == WINED3DFMT_A8R8G8B8 || destfmt == WINED3DFMT_X8R8G8B8 ||
5892        destfmt == WINED3DFMT_R8G8B8)
5893         return color;
5894
5895     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
5896
5897     a = (color & 0xff000000) >> 24;
5898     r = (color & 0x00ff0000) >> 16;
5899     g = (color & 0x0000ff00) >>  8;
5900     b = (color & 0x000000ff) >>  0;
5901
5902     switch(destfmt)
5903     {
5904         case WINED3DFMT_R5G6B5:
5905             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
5906             r = (r * 32) / 256;
5907             g = (g * 64) / 256;
5908             b = (b * 32) / 256;
5909             ret  = r << 11;
5910             ret |= g << 5;
5911             ret |= b;
5912             TRACE("Returning %08x\n", ret);
5913             return ret;
5914
5915         case WINED3DFMT_X1R5G5B5:
5916         case WINED3DFMT_A1R5G5B5:
5917             a = (a *  2) / 256;
5918             r = (r * 32) / 256;
5919             g = (g * 32) / 256;
5920             b = (b * 32) / 256;
5921             ret  = a << 15;
5922             ret |= r << 10;
5923             ret |= g <<  5;
5924             ret |= b <<  0;
5925             TRACE("Returning %08x\n", ret);
5926             return ret;
5927
5928         case WINED3DFMT_A8:
5929             TRACE("Returning %08x\n", a);
5930             return a;
5931
5932         case WINED3DFMT_X4R4G4B4:
5933         case WINED3DFMT_A4R4G4B4:
5934             a = (a * 16) / 256;
5935             r = (r * 16) / 256;
5936             g = (g * 16) / 256;
5937             b = (b * 16) / 256;
5938             ret  = a << 12;
5939             ret |= r <<  8;
5940             ret |= g <<  4;
5941             ret |= b <<  0;
5942             TRACE("Returning %08x\n", ret);
5943             return ret;
5944
5945         case WINED3DFMT_R3G3B2:
5946             r = (r * 8) / 256;
5947             g = (g * 8) / 256;
5948             b = (b * 4) / 256;
5949             ret  = r <<  5;
5950             ret |= g <<  2;
5951             ret |= b <<  0;
5952             TRACE("Returning %08x\n", ret);
5953             return ret;
5954
5955         case WINED3DFMT_X8B8G8R8:
5956         case WINED3DFMT_A8B8G8R8:
5957             ret  = a << 24;
5958             ret |= b << 16;
5959             ret |= g <<  8;
5960             ret |= r <<  0;
5961             TRACE("Returning %08x\n", ret);
5962             return ret;
5963
5964         case WINED3DFMT_A2R10G10B10:
5965             a = (a *    4) / 256;
5966             r = (r * 1024) / 256;
5967             g = (g * 1024) / 256;
5968             b = (b * 1024) / 256;
5969             ret  = a << 30;
5970             ret |= r << 20;
5971             ret |= g << 10;
5972             ret |= b <<  0;
5973             TRACE("Returning %08x\n", ret);
5974             return ret;
5975
5976         case WINED3DFMT_A2B10G10R10:
5977             a = (a *    4) / 256;
5978             r = (r * 1024) / 256;
5979             g = (g * 1024) / 256;
5980             b = (b * 1024) / 256;
5981             ret  = a << 30;
5982             ret |= b << 20;
5983             ret |= g << 10;
5984             ret |= r <<  0;
5985             TRACE("Returning %08x\n", ret);
5986             return ret;
5987
5988         default:
5989             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
5990             return 0;
5991     }
5992 }
5993
5994 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5995     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5996     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5997     WINEDDBLTFX BltFx;
5998     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
5999
6000     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6001         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6002         return WINED3DERR_INVALIDCALL;
6003     }
6004
6005     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6006         color_fill_fbo(iface, pSurface, pRect, color);
6007         return WINED3D_OK;
6008     } else {
6009         /* Just forward this to the DirectDraw blitting engine */
6010         memset(&BltFx, 0, sizeof(BltFx));
6011         BltFx.dwSize = sizeof(BltFx);
6012         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format);
6013         return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
6014     }
6015 }
6016
6017 /* rendertarget and deptth stencil functions */
6018 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6019     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6020
6021     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6022         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
6023         return WINED3DERR_INVALIDCALL;
6024     }
6025
6026     *ppRenderTarget = This->render_targets[RenderTargetIndex];
6027     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6028     /* Note inc ref on returned surface */
6029     if(*ppRenderTarget != NULL)
6030         IWineD3DSurface_AddRef(*ppRenderTarget);
6031     return WINED3D_OK;
6032 }
6033
6034 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6035     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6036     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6037     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6038     IWineD3DSwapChainImpl *Swapchain;
6039     HRESULT hr;
6040
6041     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6042
6043     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6044     if(hr != WINED3D_OK) {
6045         ERR("Can't get the swapchain\n");
6046         return hr;
6047     }
6048
6049     /* Make sure to release the swapchain */
6050     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6051
6052     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6053         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6054         return WINED3DERR_INVALIDCALL;
6055     }
6056     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6057         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6058         return WINED3DERR_INVALIDCALL;
6059     }
6060
6061     if(Swapchain->frontBuffer != Front) {
6062         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6063
6064         if(Swapchain->frontBuffer)
6065             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6066         Swapchain->frontBuffer = Front;
6067
6068         if(Swapchain->frontBuffer) {
6069             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6070         }
6071     }
6072
6073     if(Back && !Swapchain->backBuffer) {
6074         /* We need memory for the back buffer array - only one back buffer this way */
6075         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6076         if(!Swapchain->backBuffer) {
6077             ERR("Out of memory\n");
6078             return E_OUTOFMEMORY;
6079         }
6080     }
6081
6082     if(Swapchain->backBuffer[0] != Back) {
6083         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6084
6085         /* What to do about the context here in the case of multithreading? Not sure.
6086          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6087          */
6088         ENTER_GL();
6089         if(!Swapchain->backBuffer[0]) {
6090             /* GL was told to draw to the front buffer at creation,
6091              * undo that
6092              */
6093             glDrawBuffer(GL_BACK);
6094             checkGLcall("glDrawBuffer(GL_BACK)");
6095             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6096             Swapchain->presentParms.BackBufferCount = 1;
6097         } else if (!Back) {
6098             /* That makes problems - disable for now */
6099             /* glDrawBuffer(GL_FRONT); */
6100             checkGLcall("glDrawBuffer(GL_FRONT)");
6101             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6102             Swapchain->presentParms.BackBufferCount = 0;
6103         }
6104         LEAVE_GL();
6105
6106         if(Swapchain->backBuffer[0])
6107             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6108         Swapchain->backBuffer[0] = Back;
6109
6110         if(Swapchain->backBuffer[0]) {
6111             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6112         } else {
6113             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6114             Swapchain->backBuffer = NULL;
6115         }
6116
6117     }
6118
6119     return WINED3D_OK;
6120 }
6121
6122 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6124     *ppZStencilSurface = This->stencilBufferTarget;
6125     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6126
6127     if(*ppZStencilSurface != NULL) {
6128         /* Note inc ref on returned surface */
6129         IWineD3DSurface_AddRef(*ppZStencilSurface);
6130         return WINED3D_OK;
6131     } else {
6132         return WINED3DERR_NOTFOUND;
6133     }
6134 }
6135
6136 /* TODO: Handle stencil attachments */
6137 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6138     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6139     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6140
6141     TRACE("Set depth stencil to %p\n", depth_stencil);
6142
6143     if (depth_stencil_impl) {
6144         if (depth_stencil_impl->current_renderbuffer) {
6145             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
6146             checkGLcall("glFramebufferRenderbufferEXT()");
6147         } else {
6148             IWineD3DBaseTextureImpl *texture_impl;
6149             GLenum texttarget, target;
6150             GLint old_binding = 0;
6151
6152             texttarget = depth_stencil_impl->glDescription.target;
6153             if(texttarget == GL_TEXTURE_2D) {
6154                 target = GL_TEXTURE_2D;
6155                 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
6156             } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
6157                 target = GL_TEXTURE_RECTANGLE_ARB;
6158                 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
6159             } else {
6160                 target = GL_TEXTURE_CUBE_MAP_ARB;
6161                 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
6162             }
6163
6164             IWineD3DSurface_PreLoad(depth_stencil);
6165
6166             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6167             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6168             glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
6169             glBindTexture(target, old_binding);
6170
6171             /* Update base texture states array */
6172             if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
6173                 texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
6174                 texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
6175                 if (texture_impl->baseTexture.bindCount) {
6176                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
6177                 }
6178
6179                 IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
6180             }
6181
6182             GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget,
6183                     depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level));
6184             checkGLcall("glFramebufferTexture2DEXT()");
6185         }
6186     } else {
6187         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
6188         checkGLcall("glFramebufferTexture2DEXT()");
6189     }
6190 }
6191
6192 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
6193     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6194     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
6195
6196     TRACE("Set render target %u to %p\n", idx, render_target);
6197
6198     if (rtimpl) {
6199         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
6200         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
6201     } else {
6202         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
6203         checkGLcall("glFramebufferTexture2DEXT()");
6204
6205         This->draw_buffers[idx] = GL_NONE;
6206     }
6207 }
6208
6209 static void check_fbo_status(IWineD3DDevice *iface) {
6210     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6211     GLenum status;
6212
6213     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
6214     if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
6215         TRACE("FBO complete\n");
6216     } else {
6217         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
6218
6219         /* Dump the FBO attachments */
6220         if (status == GL_FRAMEBUFFER_UNSUPPORTED_EXT) {
6221             IWineD3DSurfaceImpl *attachment;
6222             int i;
6223
6224             for (i = 0; i < GL_LIMITS(buffers); ++i) {
6225                 attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
6226                 if (attachment) {
6227                     FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
6228                             attachment->pow2Width, attachment->pow2Height);
6229                 }
6230             }
6231             attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
6232             if (attachment) {
6233                 FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
6234                         attachment->pow2Width, attachment->pow2Height);
6235             }
6236         }
6237     }
6238 }
6239
6240 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
6241     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6242     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
6243     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
6244
6245     if (!ds_impl) return FALSE;
6246
6247     if (ds_impl->current_renderbuffer) {
6248         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
6249                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
6250     }
6251
6252     return (rt_impl->pow2Width != ds_impl->pow2Width ||
6253             rt_impl->pow2Height != ds_impl->pow2Height);
6254 }
6255
6256 void apply_fbo_state(IWineD3DDevice *iface) {
6257     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6258     unsigned int i;
6259
6260     if (This->render_offscreen) {
6261         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6262
6263         /* Apply render targets */
6264         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6265             IWineD3DSurface *render_target = This->render_targets[i];
6266             if (This->fbo_color_attachments[i] != render_target) {
6267                 set_render_target_fbo(iface, i, render_target);
6268                 This->fbo_color_attachments[i] = render_target;
6269             }
6270         }
6271
6272         /* Apply depth targets */
6273         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
6274             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
6275             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
6276
6277             if (This->stencilBufferTarget) {
6278                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
6279             }
6280             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
6281             This->fbo_depth_attachment = This->stencilBufferTarget;
6282         }
6283
6284         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
6285             GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
6286             checkGLcall("glDrawBuffers()");
6287         } else {
6288             glDrawBuffer(This->draw_buffers[0]);
6289             checkGLcall("glDrawBuffer()");
6290         }
6291     } else {
6292         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6293     }
6294
6295     check_fbo_status(iface);
6296 }
6297
6298 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6299         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
6300     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6301     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6302     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6303     GLenum gl_filter;
6304
6305     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6306             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6307     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6308     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6309
6310     switch (filter) {
6311         case WINED3DTEXF_LINEAR:
6312             gl_filter = GL_LINEAR;
6313             break;
6314
6315         default:
6316             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6317         case WINED3DTEXF_NONE:
6318         case WINED3DTEXF_POINT:
6319             gl_filter = GL_NEAREST;
6320             break;
6321     }
6322
6323     /* Attach src surface to src fbo */
6324     src_swapchain = get_swapchain(src_surface);
6325     if (src_swapchain) {
6326         GLenum buffer;
6327
6328         TRACE("Source surface %p is onscreen\n", src_surface);
6329         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6330
6331         ENTER_GL();
6332         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
6333         buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6334         glReadBuffer(buffer);
6335         checkGLcall("glReadBuffer()");
6336
6337         src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6338         src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6339     } else {
6340         TRACE("Source surface %p is offscreen\n", src_surface);
6341         ENTER_GL();
6342         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
6343         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
6344         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
6345         checkGLcall("glReadBuffer()");
6346     }
6347     LEAVE_GL();
6348
6349     /* Attach dst surface to dst fbo */
6350     dst_swapchain = get_swapchain(dst_surface);
6351     if (dst_swapchain) {
6352         GLenum buffer;
6353
6354         TRACE("Destination surface %p is onscreen\n", dst_surface);
6355         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6356
6357         ENTER_GL();
6358         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
6359         buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6360         glDrawBuffer(buffer);
6361         checkGLcall("glDrawBuffer()");
6362
6363         dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6364         dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6365     } else {
6366         TRACE("Destination surface %p is offscreen\n", dst_surface);
6367
6368         /* No src or dst swapchain? Make sure some context is active(multithreading) */
6369         if(!src_swapchain) {
6370             ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6371         }
6372
6373         ENTER_GL();
6374         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
6375         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
6376         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
6377         checkGLcall("glDrawBuffer()");
6378     }
6379     glDisable(GL_SCISSOR_TEST);
6380     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6381
6382     if (flip) {
6383         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6384                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
6385         checkGLcall("glBlitFramebuffer()");
6386     } else {
6387         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6388                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
6389         checkGLcall("glBlitFramebuffer()");
6390     }
6391
6392     if (This->render_offscreen) {
6393         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6394     } else {
6395         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6396         checkGLcall("glBindFramebuffer()");
6397     }
6398
6399     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6400     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6401             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6402         glDrawBuffer(GL_BACK);
6403         checkGLcall("glDrawBuffer()");
6404     }
6405     LEAVE_GL();
6406 }
6407
6408 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6409     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6410     WINED3DVIEWPORT viewport;
6411
6412     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6413
6414     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6415         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6416              This, RenderTargetIndex, GL_LIMITS(buffers));
6417         return WINED3DERR_INVALIDCALL;
6418     }
6419
6420     /* MSDN says that null disables the render target
6421     but a device must always be associated with a render target
6422     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6423
6424     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6425     for more details
6426     */
6427     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6428         FIXME("Trying to set render target 0 to NULL\n");
6429         return WINED3DERR_INVALIDCALL;
6430     }
6431     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6432         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);
6433         return WINED3DERR_INVALIDCALL;
6434     }
6435
6436     /* If we are trying to set what we already have, don't bother */
6437     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6438         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6439         return WINED3D_OK;
6440     }
6441     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6442     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6443     This->render_targets[RenderTargetIndex] = pRenderTarget;
6444
6445     /* Render target 0 is special */
6446     if(RenderTargetIndex == 0) {
6447         /* Finally, reset the viewport as the MSDN states. */
6448         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6449         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6450         viewport.X      = 0;
6451         viewport.Y      = 0;
6452         viewport.MaxZ   = 1.0f;
6453         viewport.MinZ   = 0.0f;
6454         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6455         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6456          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6457          */
6458         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
6459
6460         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
6461          * ctx properly.
6462          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
6463          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
6464          */
6465         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
6466     }
6467     return WINED3D_OK;
6468 }
6469
6470 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6471     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6472     HRESULT  hr = WINED3D_OK;
6473     IWineD3DSurface *tmp;
6474
6475     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6476
6477     if (pNewZStencil == This->stencilBufferTarget) {
6478         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6479     } else {
6480         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6481         * depending on the renter target implementation being used.
6482         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6483         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6484         * stencil buffer and incure an extra memory overhead
6485          ******************************************************/
6486
6487         tmp = This->stencilBufferTarget;
6488         This->stencilBufferTarget = pNewZStencil;
6489         This->depth_copy_state = WINED3D_DCS_NO_COPY;
6490         /* should we be calling the parent or the wined3d surface? */
6491         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6492         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6493         hr = WINED3D_OK;
6494
6495         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6496             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6497             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6498             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6499             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6500         }
6501     }
6502
6503     return hr;
6504 }
6505
6506 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6507                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6508     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6509     /* TODO: the use of Impl is deprecated. */
6510     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6511     WINED3DLOCKED_RECT lockedRect;
6512
6513     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6514
6515     /* some basic validation checks */
6516     if(This->cursorTexture) {
6517         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6518         ENTER_GL();
6519         glDeleteTextures(1, &This->cursorTexture);
6520         LEAVE_GL();
6521         This->cursorTexture = 0;
6522     }
6523
6524     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6525         This->haveHardwareCursor = TRUE;
6526     else
6527         This->haveHardwareCursor = FALSE;
6528
6529     if(pCursorBitmap) {
6530         WINED3DLOCKED_RECT rect;
6531
6532         /* MSDN: Cursor must be A8R8G8B8 */
6533         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6534             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6535             return WINED3DERR_INVALIDCALL;
6536         }
6537
6538         /* MSDN: Cursor must be smaller than the display mode */
6539         if(pSur->currentDesc.Width > This->ddraw_width ||
6540            pSur->currentDesc.Height > This->ddraw_height) {
6541             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);
6542             return WINED3DERR_INVALIDCALL;
6543         }
6544
6545         if (!This->haveHardwareCursor) {
6546             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6547
6548             /* Do not store the surface's pointer because the application may
6549              * release it after setting the cursor image. Windows doesn't
6550              * addref the set surface, so we can't do this either without
6551              * creating circular refcount dependencies. Copy out the gl texture
6552              * instead.
6553              */
6554             This->cursorWidth = pSur->currentDesc.Width;
6555             This->cursorHeight = pSur->currentDesc.Height;
6556             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6557             {
6558                 const GlPixelFormatDesc *glDesc;
6559                 const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION, &glDesc);
6560                 char *mem, *bits = (char *)rect.pBits;
6561                 GLint intfmt = glDesc->glInternal;
6562                 GLint format = glDesc->glFormat;
6563                 GLint type = glDesc->glType;
6564                 INT height = This->cursorHeight;
6565                 INT width = This->cursorWidth;
6566                 INT bpp = tableEntry->bpp;
6567                 INT i;
6568
6569                 /* Reformat the texture memory (pitch and width can be
6570                  * different) */
6571                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6572                 for(i = 0; i < height; i++)
6573                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6574                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6575                 ENTER_GL();
6576
6577                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6578                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6579                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6580                 }
6581
6582                 /* Make sure that a proper texture unit is selected */
6583                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
6584                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6585                     checkGLcall("glActiveTextureARB");
6586                 }
6587                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
6588                 /* Create a new cursor texture */
6589                 glGenTextures(1, &This->cursorTexture);
6590                 checkGLcall("glGenTextures");
6591                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6592                 checkGLcall("glBindTexture");
6593                 /* Copy the bitmap memory into the cursor texture */
6594                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6595                 HeapFree(GetProcessHeap(), 0, mem);
6596                 checkGLcall("glTexImage2D");
6597
6598                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6599                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6600                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6601                 }
6602
6603                 LEAVE_GL();
6604             }
6605             else
6606             {
6607                 FIXME("A cursor texture was not returned.\n");
6608                 This->cursorTexture = 0;
6609             }
6610         }
6611         else
6612         {
6613             /* Draw a hardware cursor */
6614             ICONINFO cursorInfo;
6615             HCURSOR cursor;
6616             /* Create and clear maskBits because it is not needed for
6617              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6618              * chunks. */
6619             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6620                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6621             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6622                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6623                                          WINED3DLOCK_READONLY
6624             );
6625             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6626                   pSur->currentDesc.Height);
6627
6628             cursorInfo.fIcon = FALSE;
6629             cursorInfo.xHotspot = XHotSpot;
6630             cursorInfo.yHotspot = YHotSpot;
6631             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
6632                                               pSur->currentDesc.Height, 1,
6633                                               1, &maskBits);
6634             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
6635                                                pSur->currentDesc.Height, 1,
6636                                                32, lockedRect.pBits);
6637             IWineD3DSurface_UnlockRect(pCursorBitmap);
6638             /* Create our cursor and clean up. */
6639             cursor = CreateIconIndirect(&cursorInfo);
6640             SetCursor(cursor);
6641             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6642             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6643             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6644             This->hardwareCursor = cursor;
6645             HeapFree(GetProcessHeap(), 0, maskBits);
6646         }
6647     }
6648
6649     This->xHotSpot = XHotSpot;
6650     This->yHotSpot = YHotSpot;
6651     return WINED3D_OK;
6652 }
6653
6654 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6656     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6657
6658     This->xScreenSpace = XScreenSpace;
6659     This->yScreenSpace = YScreenSpace;
6660
6661     return;
6662
6663 }
6664
6665 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6666     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6667     BOOL oldVisible = This->bCursorVisible;
6668     POINT pt;
6669
6670     TRACE("(%p) : visible(%d)\n", This, bShow);
6671
6672     /*
6673      * When ShowCursor is first called it should make the cursor appear at the OS's last
6674      * known cursor position.  Because of this, some applications just repetitively call
6675      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6676      */
6677     GetCursorPos(&pt);
6678     This->xScreenSpace = pt.x;
6679     This->yScreenSpace = pt.y;
6680
6681     if (This->haveHardwareCursor) {
6682         This->bCursorVisible = bShow;
6683         if (bShow)
6684             SetCursor(This->hardwareCursor);
6685         else
6686             SetCursor(NULL);
6687     }
6688     else
6689     {
6690         if (This->cursorTexture)
6691             This->bCursorVisible = bShow;
6692     }
6693
6694     return oldVisible;
6695 }
6696
6697 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6698     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6699     IWineD3DResourceImpl *resource;
6700     TRACE("(%p) : state (%u)\n", This, This->state);
6701
6702     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6703     switch (This->state) {
6704     case WINED3D_OK:
6705         return WINED3D_OK;
6706     case WINED3DERR_DEVICELOST:
6707         {
6708             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6709                 if (resource->resource.pool == WINED3DPOOL_DEFAULT)
6710                     return WINED3DERR_DEVICENOTRESET;
6711             }
6712             return WINED3DERR_DEVICELOST;
6713         }
6714     case WINED3DERR_DRIVERINTERNALERROR:
6715         return WINED3DERR_DRIVERINTERNALERROR;
6716     }
6717
6718     /* Unknown state */
6719     return WINED3DERR_DRIVERINTERNALERROR;
6720 }
6721
6722
6723 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6724     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6725     /** FIXME: Resource tracking needs to be done,
6726     * The closes we can do to this is set the priorities of all managed textures low
6727     * and then reset them.
6728      ***********************************************************/
6729     FIXME("(%p) : stub\n", This);
6730     return WINED3D_OK;
6731 }
6732
6733 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6734     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
6735
6736     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6737     if(surface->Flags & SFLAG_DIBSECTION) {
6738         /* Release the DC */
6739         SelectObject(surface->hDC, surface->dib.holdbitmap);
6740         DeleteDC(surface->hDC);
6741         /* Release the DIB section */
6742         DeleteObject(surface->dib.DIBsection);
6743         surface->dib.bitmap_data = NULL;
6744         surface->resource.allocatedMemory = NULL;
6745         surface->Flags &= ~SFLAG_DIBSECTION;
6746     }
6747     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6748     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6749     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
6750         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6751         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6752     } else {
6753         surface->pow2Width = surface->pow2Height = 1;
6754         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6755         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6756     }
6757     if(surface->glDescription.textureName) {
6758         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6759         ENTER_GL();
6760         glDeleteTextures(1, &surface->glDescription.textureName);
6761         LEAVE_GL();
6762         surface->glDescription.textureName = 0;
6763         surface->Flags &= ~SFLAG_CLIENT;
6764     }
6765     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6766        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6767         surface->Flags |= SFLAG_NONPOW2;
6768     } else  {
6769         surface->Flags &= ~SFLAG_NONPOW2;
6770     }
6771     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
6772     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6773 }
6774
6775 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6776     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6777     IWineD3DSwapChainImpl *swapchain;
6778     HRESULT hr;
6779     BOOL DisplayModeChanged = FALSE;
6780     WINED3DDISPLAYMODE mode;
6781     TRACE("(%p)\n", This);
6782
6783     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6784     if(FAILED(hr)) {
6785         ERR("Failed to get the first implicit swapchain\n");
6786         return hr;
6787     }
6788
6789     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6790      * on an existing gl context, so there's no real need for recreation.
6791      *
6792      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6793      *
6794      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6795      */
6796     TRACE("New params:\n");
6797     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6798     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6799     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6800     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6801     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6802     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6803     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6804     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6805     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6806     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6807     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6808     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6809     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6810
6811     /* No special treatment of these parameters. Just store them */
6812     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6813     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6814     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6815     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6816
6817     /* What to do about these? */
6818     if(pPresentationParameters->BackBufferCount != 0 &&
6819         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6820         ERR("Cannot change the back buffer count yet\n");
6821     }
6822     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6823         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6824         ERR("Cannot change the back buffer format yet\n");
6825     }
6826     if(pPresentationParameters->hDeviceWindow != NULL &&
6827         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6828         ERR("Cannot change the device window yet\n");
6829     }
6830     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6831         ERR("What do do about a changed auto depth stencil parameter?\n");
6832     }
6833
6834     if(pPresentationParameters->Windowed) {
6835         mode.Width = swapchain->orig_width;
6836         mode.Height = swapchain->orig_height;
6837         mode.RefreshRate = 0;
6838         mode.Format = swapchain->presentParms.BackBufferFormat;
6839     } else {
6840         mode.Width = pPresentationParameters->BackBufferWidth;
6841         mode.Height = pPresentationParameters->BackBufferHeight;
6842         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6843         mode.Format = swapchain->presentParms.BackBufferFormat;
6844     }
6845
6846     /* Should Width == 800 && Height == 0 set 800x600? */
6847     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6848        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6849         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6850     {
6851         WINED3DVIEWPORT vp;
6852         int i;
6853
6854         vp.X = 0;
6855         vp.Y = 0;
6856         vp.Width = pPresentationParameters->BackBufferWidth;
6857         vp.Height = pPresentationParameters->BackBufferHeight;
6858         vp.MinZ = 0;
6859         vp.MaxZ = 1;
6860
6861         if(!pPresentationParameters->Windowed) {
6862             DisplayModeChanged = TRUE;
6863         }
6864         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6865         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6866
6867         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6868         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6869             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6870         }
6871
6872         /* Now set the new viewport */
6873         IWineD3DDevice_SetViewport(iface, &vp);
6874     }
6875
6876     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6877        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
6878         DisplayModeChanged) {
6879
6880         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
6881         if(!pPresentationParameters->Windowed) {
6882             IWineD3DDevice_SetFullscreen(iface, TRUE);
6883         }
6884
6885         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6886
6887         /* Switching out of fullscreen mode? First set the original res, then change the window */
6888         if(pPresentationParameters->Windowed) {
6889             IWineD3DDevice_SetFullscreen(iface, FALSE);
6890         }
6891         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6892     }
6893
6894     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6895     return WINED3D_OK;
6896 }
6897
6898 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6899     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6900     /** FIXME: always true at the moment **/
6901     if(!bEnableDialogs) {
6902         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6903     }
6904     return WINED3D_OK;
6905 }
6906
6907
6908 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6909     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6910     TRACE("(%p) : pParameters %p\n", This, pParameters);
6911
6912     *pParameters = This->createParms;
6913     return WINED3D_OK;
6914 }
6915
6916 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6917     IWineD3DSwapChain *swapchain;
6918     HRESULT hrc = WINED3D_OK;
6919
6920     TRACE("Relaying  to swapchain\n");
6921
6922     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6923         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6924         IWineD3DSwapChain_Release(swapchain);
6925     }
6926     return;
6927 }
6928
6929 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6930     IWineD3DSwapChain *swapchain;
6931     HRESULT hrc = WINED3D_OK;
6932
6933     TRACE("Relaying  to swapchain\n");
6934
6935     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6936         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6937         IWineD3DSwapChain_Release(swapchain);
6938     }
6939     return;
6940 }
6941
6942
6943 /** ********************************************************
6944 *   Notification functions
6945 ** ********************************************************/
6946 /** This function must be called in the release of a resource when ref == 0,
6947 * the contents of resource must still be correct,
6948 * any handels to other resource held by the caller must be closed
6949 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6950  *****************************************************/
6951 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6952     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6953
6954     TRACE("(%p) : Adding Resource %p\n", This, resource);
6955     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6956 }
6957
6958 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6959     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6960
6961     TRACE("(%p) : Removing resource %p\n", This, resource);
6962
6963     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6964 }
6965
6966
6967 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6968     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6969     int counter;
6970
6971     TRACE("(%p) : resource %p\n", This, resource);
6972     switch(IWineD3DResource_GetType(resource)){
6973         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6974         case WINED3DRTYPE_SURFACE: {
6975             unsigned int i;
6976
6977             /* Cleanup any FBO attachments if d3d is enabled */
6978             if(This->d3d_initialized) {
6979                 if((IWineD3DSurface *)resource == This->lastActiveRenderTarget) {
6980                     IWineD3DSwapChainImpl *swapchain = This->swapchains ? (IWineD3DSwapChainImpl *) This->swapchains[0] : NULL;
6981
6982                     TRACE("Last active render target destroyed\n");
6983                     /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
6984                      * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
6985                      * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
6986                      * and the lastActiveRenderTarget member shouldn't matter
6987                      */
6988                     if(swapchain) {
6989                         if(swapchain->backBuffer && swapchain->backBuffer[0] != (IWineD3DSurface *)resource) {
6990                             TRACE("Activating primary back buffer\n");
6991                             ActivateContext(This, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
6992                         } else if(!swapchain->backBuffer && swapchain->frontBuffer != (IWineD3DSurface *)resource) {
6993                             /* Single buffering environment */
6994                             TRACE("Activating primary front buffer\n");
6995                             ActivateContext(This, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD);
6996                         } else {
6997                             TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
6998                             /* Implicit render target destroyed, that means the device is being destroyed
6999                              * whatever we set here, it shouldn't matter
7000                              */
7001                             This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
7002                         }
7003                     } else {
7004                         /* May happen during ddraw uninitialization */
7005                         TRACE("Render target set, but swapchain does not exist!\n");
7006                         This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe;
7007                     }
7008                 }
7009
7010                 for (i = 0; i < GL_LIMITS(buffers); ++i) {
7011                     if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
7012                         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7013                         set_render_target_fbo(iface, i, NULL);
7014                         This->fbo_color_attachments[i] = NULL;
7015                     }
7016                 }
7017                 if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
7018                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7019                     set_depth_stencil_fbo(iface, NULL);
7020                     This->fbo_depth_attachment = NULL;
7021                 }
7022             }
7023
7024             break;
7025         }
7026         case WINED3DRTYPE_TEXTURE:
7027         case WINED3DRTYPE_CUBETEXTURE:
7028         case WINED3DRTYPE_VOLUMETEXTURE:
7029                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
7030                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7031                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7032                         This->stateBlock->textures[counter] = NULL;
7033                     }
7034                     if (This->updateStateBlock != This->stateBlock ){
7035                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7036                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7037                             This->updateStateBlock->textures[counter] = NULL;
7038                         }
7039                     }
7040                 }
7041         break;
7042         case WINED3DRTYPE_VOLUME:
7043         /* TODO: nothing really? */
7044         break;
7045         case WINED3DRTYPE_VERTEXBUFFER:
7046         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7047         {
7048             int streamNumber;
7049             TRACE("Cleaning up stream pointers\n");
7050
7051             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7052                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7053                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7054                 */
7055                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7056                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7057                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7058                         This->updateStateBlock->streamSource[streamNumber] = 0;
7059                         /* Set changed flag? */
7060                     }
7061                 }
7062                 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) */
7063                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7064                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7065                         This->stateBlock->streamSource[streamNumber] = 0;
7066                     }
7067                 }
7068 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7069                  else { /* This shouldn't happen */
7070                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7071                 }
7072 #endif
7073
7074             }
7075         }
7076         break;
7077         case WINED3DRTYPE_INDEXBUFFER:
7078         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7079         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7080             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7081                 This->updateStateBlock->pIndexData =  NULL;
7082             }
7083         }
7084         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7085             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7086                 This->stateBlock->pIndexData =  NULL;
7087             }
7088         }
7089
7090         break;
7091         default:
7092         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7093         break;
7094     }
7095
7096
7097     /* Remove the resoruce from the resourceStore */
7098     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7099
7100     TRACE("Resource released\n");
7101
7102 }
7103
7104 /**********************************************************
7105  * IWineD3DDevice VTbl follows
7106  **********************************************************/
7107
7108 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7109 {
7110     /*** IUnknown methods ***/
7111     IWineD3DDeviceImpl_QueryInterface,
7112     IWineD3DDeviceImpl_AddRef,
7113     IWineD3DDeviceImpl_Release,
7114     /*** IWineD3DDevice methods ***/
7115     IWineD3DDeviceImpl_GetParent,
7116     /*** Creation methods**/
7117     IWineD3DDeviceImpl_CreateVertexBuffer,
7118     IWineD3DDeviceImpl_CreateIndexBuffer,
7119     IWineD3DDeviceImpl_CreateStateBlock,
7120     IWineD3DDeviceImpl_CreateSurface,
7121     IWineD3DDeviceImpl_CreateTexture,
7122     IWineD3DDeviceImpl_CreateVolumeTexture,
7123     IWineD3DDeviceImpl_CreateVolume,
7124     IWineD3DDeviceImpl_CreateCubeTexture,
7125     IWineD3DDeviceImpl_CreateQuery,
7126     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7127     IWineD3DDeviceImpl_CreateVertexDeclaration,
7128     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7129     IWineD3DDeviceImpl_CreateVertexShader,
7130     IWineD3DDeviceImpl_CreatePixelShader,
7131     IWineD3DDeviceImpl_CreatePalette,
7132     /*** Odd functions **/
7133     IWineD3DDeviceImpl_Init3D,
7134     IWineD3DDeviceImpl_Uninit3D,
7135     IWineD3DDeviceImpl_SetFullscreen,
7136     IWineD3DDeviceImpl_SetMultithreaded,
7137     IWineD3DDeviceImpl_EvictManagedResources,
7138     IWineD3DDeviceImpl_GetAvailableTextureMem,
7139     IWineD3DDeviceImpl_GetBackBuffer,
7140     IWineD3DDeviceImpl_GetCreationParameters,
7141     IWineD3DDeviceImpl_GetDeviceCaps,
7142     IWineD3DDeviceImpl_GetDirect3D,
7143     IWineD3DDeviceImpl_GetDisplayMode,
7144     IWineD3DDeviceImpl_SetDisplayMode,
7145     IWineD3DDeviceImpl_GetHWND,
7146     IWineD3DDeviceImpl_SetHWND,
7147     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7148     IWineD3DDeviceImpl_GetRasterStatus,
7149     IWineD3DDeviceImpl_GetSwapChain,
7150     IWineD3DDeviceImpl_Reset,
7151     IWineD3DDeviceImpl_SetDialogBoxMode,
7152     IWineD3DDeviceImpl_SetCursorProperties,
7153     IWineD3DDeviceImpl_SetCursorPosition,
7154     IWineD3DDeviceImpl_ShowCursor,
7155     IWineD3DDeviceImpl_TestCooperativeLevel,
7156     /*** Getters and setters **/
7157     IWineD3DDeviceImpl_SetClipPlane,
7158     IWineD3DDeviceImpl_GetClipPlane,
7159     IWineD3DDeviceImpl_SetClipStatus,
7160     IWineD3DDeviceImpl_GetClipStatus,
7161     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7162     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7163     IWineD3DDeviceImpl_SetDepthStencilSurface,
7164     IWineD3DDeviceImpl_GetDepthStencilSurface,
7165     IWineD3DDeviceImpl_SetFVF,
7166     IWineD3DDeviceImpl_GetFVF,
7167     IWineD3DDeviceImpl_SetGammaRamp,
7168     IWineD3DDeviceImpl_GetGammaRamp,
7169     IWineD3DDeviceImpl_SetIndices,
7170     IWineD3DDeviceImpl_GetIndices,
7171     IWineD3DDeviceImpl_SetBaseVertexIndex,
7172     IWineD3DDeviceImpl_GetBaseVertexIndex,
7173     IWineD3DDeviceImpl_SetLight,
7174     IWineD3DDeviceImpl_GetLight,
7175     IWineD3DDeviceImpl_SetLightEnable,
7176     IWineD3DDeviceImpl_GetLightEnable,
7177     IWineD3DDeviceImpl_SetMaterial,
7178     IWineD3DDeviceImpl_GetMaterial,
7179     IWineD3DDeviceImpl_SetNPatchMode,
7180     IWineD3DDeviceImpl_GetNPatchMode,
7181     IWineD3DDeviceImpl_SetPaletteEntries,
7182     IWineD3DDeviceImpl_GetPaletteEntries,
7183     IWineD3DDeviceImpl_SetPixelShader,
7184     IWineD3DDeviceImpl_GetPixelShader,
7185     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7186     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7187     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7188     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7189     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7190     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7191     IWineD3DDeviceImpl_SetRenderState,
7192     IWineD3DDeviceImpl_GetRenderState,
7193     IWineD3DDeviceImpl_SetRenderTarget,
7194     IWineD3DDeviceImpl_GetRenderTarget,
7195     IWineD3DDeviceImpl_SetFrontBackBuffers,
7196     IWineD3DDeviceImpl_SetSamplerState,
7197     IWineD3DDeviceImpl_GetSamplerState,
7198     IWineD3DDeviceImpl_SetScissorRect,
7199     IWineD3DDeviceImpl_GetScissorRect,
7200     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7201     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7202     IWineD3DDeviceImpl_SetStreamSource,
7203     IWineD3DDeviceImpl_GetStreamSource,
7204     IWineD3DDeviceImpl_SetStreamSourceFreq,
7205     IWineD3DDeviceImpl_GetStreamSourceFreq,
7206     IWineD3DDeviceImpl_SetTexture,
7207     IWineD3DDeviceImpl_GetTexture,
7208     IWineD3DDeviceImpl_SetTextureStageState,
7209     IWineD3DDeviceImpl_GetTextureStageState,
7210     IWineD3DDeviceImpl_SetTransform,
7211     IWineD3DDeviceImpl_GetTransform,
7212     IWineD3DDeviceImpl_SetVertexDeclaration,
7213     IWineD3DDeviceImpl_GetVertexDeclaration,
7214     IWineD3DDeviceImpl_SetVertexShader,
7215     IWineD3DDeviceImpl_GetVertexShader,
7216     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7217     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7218     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7219     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7220     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7221     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7222     IWineD3DDeviceImpl_SetViewport,
7223     IWineD3DDeviceImpl_GetViewport,
7224     IWineD3DDeviceImpl_MultiplyTransform,
7225     IWineD3DDeviceImpl_ValidateDevice,
7226     IWineD3DDeviceImpl_ProcessVertices,
7227     /*** State block ***/
7228     IWineD3DDeviceImpl_BeginStateBlock,
7229     IWineD3DDeviceImpl_EndStateBlock,
7230     /*** Scene management ***/
7231     IWineD3DDeviceImpl_BeginScene,
7232     IWineD3DDeviceImpl_EndScene,
7233     IWineD3DDeviceImpl_Present,
7234     IWineD3DDeviceImpl_Clear,
7235     /*** Drawing ***/
7236     IWineD3DDeviceImpl_DrawPrimitive,
7237     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7238     IWineD3DDeviceImpl_DrawPrimitiveUP,
7239     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7240     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7241     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7242     IWineD3DDeviceImpl_DrawRectPatch,
7243     IWineD3DDeviceImpl_DrawTriPatch,
7244     IWineD3DDeviceImpl_DeletePatch,
7245     IWineD3DDeviceImpl_ColorFill,
7246     IWineD3DDeviceImpl_UpdateTexture,
7247     IWineD3DDeviceImpl_UpdateSurface,
7248     IWineD3DDeviceImpl_GetFrontBufferData,
7249     /*** object tracking ***/
7250     IWineD3DDeviceImpl_ResourceReleased
7251 };
7252
7253
7254 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7255     WINED3DRS_ALPHABLENDENABLE   ,
7256     WINED3DRS_ALPHAFUNC          ,
7257     WINED3DRS_ALPHAREF           ,
7258     WINED3DRS_ALPHATESTENABLE    ,
7259     WINED3DRS_BLENDOP            ,
7260     WINED3DRS_COLORWRITEENABLE   ,
7261     WINED3DRS_DESTBLEND          ,
7262     WINED3DRS_DITHERENABLE       ,
7263     WINED3DRS_FILLMODE           ,
7264     WINED3DRS_FOGDENSITY         ,
7265     WINED3DRS_FOGEND             ,
7266     WINED3DRS_FOGSTART           ,
7267     WINED3DRS_LASTPIXEL          ,
7268     WINED3DRS_SHADEMODE          ,
7269     WINED3DRS_SRCBLEND           ,
7270     WINED3DRS_STENCILENABLE      ,
7271     WINED3DRS_STENCILFAIL        ,
7272     WINED3DRS_STENCILFUNC        ,
7273     WINED3DRS_STENCILMASK        ,
7274     WINED3DRS_STENCILPASS        ,
7275     WINED3DRS_STENCILREF         ,
7276     WINED3DRS_STENCILWRITEMASK   ,
7277     WINED3DRS_STENCILZFAIL       ,
7278     WINED3DRS_TEXTUREFACTOR      ,
7279     WINED3DRS_WRAP0              ,
7280     WINED3DRS_WRAP1              ,
7281     WINED3DRS_WRAP2              ,
7282     WINED3DRS_WRAP3              ,
7283     WINED3DRS_WRAP4              ,
7284     WINED3DRS_WRAP5              ,
7285     WINED3DRS_WRAP6              ,
7286     WINED3DRS_WRAP7              ,
7287     WINED3DRS_ZENABLE            ,
7288     WINED3DRS_ZFUNC              ,
7289     WINED3DRS_ZWRITEENABLE
7290 };
7291
7292 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7293     WINED3DTSS_ADDRESSW              ,
7294     WINED3DTSS_ALPHAARG0             ,
7295     WINED3DTSS_ALPHAARG1             ,
7296     WINED3DTSS_ALPHAARG2             ,
7297     WINED3DTSS_ALPHAOP               ,
7298     WINED3DTSS_BUMPENVLOFFSET        ,
7299     WINED3DTSS_BUMPENVLSCALE         ,
7300     WINED3DTSS_BUMPENVMAT00          ,
7301     WINED3DTSS_BUMPENVMAT01          ,
7302     WINED3DTSS_BUMPENVMAT10          ,
7303     WINED3DTSS_BUMPENVMAT11          ,
7304     WINED3DTSS_COLORARG0             ,
7305     WINED3DTSS_COLORARG1             ,
7306     WINED3DTSS_COLORARG2             ,
7307     WINED3DTSS_COLOROP               ,
7308     WINED3DTSS_RESULTARG             ,
7309     WINED3DTSS_TEXCOORDINDEX         ,
7310     WINED3DTSS_TEXTURETRANSFORMFLAGS
7311 };
7312
7313 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7314     WINED3DSAMP_ADDRESSU         ,
7315     WINED3DSAMP_ADDRESSV         ,
7316     WINED3DSAMP_ADDRESSW         ,
7317     WINED3DSAMP_BORDERCOLOR      ,
7318     WINED3DSAMP_MAGFILTER        ,
7319     WINED3DSAMP_MINFILTER        ,
7320     WINED3DSAMP_MIPFILTER        ,
7321     WINED3DSAMP_MIPMAPLODBIAS    ,
7322     WINED3DSAMP_MAXMIPLEVEL      ,
7323     WINED3DSAMP_MAXANISOTROPY    ,
7324     WINED3DSAMP_SRGBTEXTURE      ,
7325     WINED3DSAMP_ELEMENTINDEX
7326 };
7327
7328 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7329     WINED3DRS_AMBIENT                       ,
7330     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7331     WINED3DRS_CLIPPING                      ,
7332     WINED3DRS_CLIPPLANEENABLE               ,
7333     WINED3DRS_COLORVERTEX                   ,
7334     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7335     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7336     WINED3DRS_FOGDENSITY                    ,
7337     WINED3DRS_FOGEND                        ,
7338     WINED3DRS_FOGSTART                      ,
7339     WINED3DRS_FOGTABLEMODE                  ,
7340     WINED3DRS_FOGVERTEXMODE                 ,
7341     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7342     WINED3DRS_LIGHTING                      ,
7343     WINED3DRS_LOCALVIEWER                   ,
7344     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7345     WINED3DRS_MULTISAMPLEMASK               ,
7346     WINED3DRS_NORMALIZENORMALS              ,
7347     WINED3DRS_PATCHEDGESTYLE                ,
7348     WINED3DRS_POINTSCALE_A                  ,
7349     WINED3DRS_POINTSCALE_B                  ,
7350     WINED3DRS_POINTSCALE_C                  ,
7351     WINED3DRS_POINTSCALEENABLE              ,
7352     WINED3DRS_POINTSIZE                     ,
7353     WINED3DRS_POINTSIZE_MAX                 ,
7354     WINED3DRS_POINTSIZE_MIN                 ,
7355     WINED3DRS_POINTSPRITEENABLE             ,
7356     WINED3DRS_RANGEFOGENABLE                ,
7357     WINED3DRS_SPECULARMATERIALSOURCE        ,
7358     WINED3DRS_TWEENFACTOR                   ,
7359     WINED3DRS_VERTEXBLEND                   ,
7360     WINED3DRS_CULLMODE                      ,
7361     WINED3DRS_FOGCOLOR
7362 };
7363
7364 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7365     WINED3DTSS_TEXCOORDINDEX         ,
7366     WINED3DTSS_TEXTURETRANSFORMFLAGS
7367 };
7368
7369 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7370     WINED3DSAMP_DMAPOFFSET
7371 };
7372
7373 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7374     DWORD rep = StateTable[state].representative;
7375     DWORD idx;
7376     BYTE shift;
7377     UINT i;
7378     WineD3DContext *context;
7379
7380     if(!rep) return;
7381     for(i = 0; i < This->numContexts; i++) {
7382         context = This->contexts[i];
7383         if(isStateDirty(context, rep)) continue;
7384
7385         context->dirtyArray[context->numDirtyEntries++] = rep;
7386         idx = rep >> 5;
7387         shift = rep & 0x1f;
7388         context->isStateDirty[idx] |= (1 << shift);
7389     }
7390 }
7391
7392 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7393     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7394     /* The drawable size of a pbuffer render target is the current pbuffer size
7395      */
7396     *width = dev->pbufferWidth;
7397     *height = dev->pbufferHeight;
7398 }
7399
7400 void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7401     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
7402      */
7403     *width = This->pow2Width;
7404     *height = This->pow2Height;
7405 }
7406
7407 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7408     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7409     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7410      * current context's drawable, which is the size of the back buffer of the swapchain
7411      * the active context belongs to. The back buffer of the swapchain is stored as the
7412      * surface the context belongs to.
7413      */
7414     *width = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Width;
7415     *height = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Height;
7416 }