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