wined3d: Fix a typo.
[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, &This->adapter->gl_info);
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 vertex 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
1694     for (i = 0; i < This->adapter->gl_info.max_textures; ++i)
1695     {
1696         GLubyte white = 255;
1697
1698         /* Make appropriate texture active */
1699         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1700         checkGLcall("glActiveTextureARB");
1701
1702         /* Generate an opengl texture name */
1703         glGenTextures(1, &This->dummyTextureName[i]);
1704         checkGLcall("glGenTextures");
1705         TRACE("Dummy Texture %d given name %d\n", i, This->dummyTextureName[i]);
1706
1707         /* Generate a dummy 2d texture (not using 1d because they cause many
1708         * DRI drivers fall back to sw) */
1709         glBindTexture(GL_TEXTURE_2D, This->dummyTextureName[i]);
1710         checkGLcall("glBindTexture");
1711
1712         glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
1713         checkGLcall("glTexImage2D");
1714     }
1715     if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
1716         /* Reenable because if supported it is enabled by default */
1717         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1718         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1719     }
1720
1721     LEAVE_GL();
1722 }
1723
1724 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface,
1725         WINED3DPRESENT_PARAMETERS *pPresentationParameters)
1726 {
1727     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1728     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
1729     IWineD3DSwapChainImpl *swapchain = NULL;
1730     HRESULT hr;
1731     DWORD state;
1732     unsigned int i;
1733
1734     TRACE("(%p)->(%p)\n", This, pPresentationParameters);
1735
1736     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1737     if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL;
1738
1739     /* TODO: Test if OpenGL is compiled in and loaded */
1740
1741     TRACE("(%p) : Creating stateblock\n", This);
1742     /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
1743     hr = IWineD3DDevice_CreateStateBlock(iface,
1744                                          WINED3DSBT_INIT,
1745                                          (IWineD3DStateBlock **)&This->stateBlock,
1746                                          NULL);
1747     if (WINED3D_OK != hr) {   /* Note: No parent needed for initial internal stateblock */
1748         WARN("Failed to create stateblock\n");
1749         goto err_out;
1750     }
1751     TRACE("(%p) : Created stateblock (%p)\n", This, This->stateBlock);
1752     This->updateStateBlock = This->stateBlock;
1753     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
1754
1755     This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1756             sizeof(IWineD3DSurface *) * gl_info->max_buffers);
1757     This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1758             sizeof(GLenum) * gl_info->max_buffers);
1759
1760     This->NumberOfPalettes = 1;
1761     This->palettes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PALETTEENTRY*));
1762     if(!This->palettes || !This->render_targets || !This->draw_buffers) {
1763         ERR("Out of memory!\n");
1764         goto err_out;
1765     }
1766     This->palettes[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256);
1767     if(!This->palettes[0]) {
1768         ERR("Out of memory!\n");
1769         goto err_out;
1770     }
1771     for (i = 0; i < 256; ++i) {
1772         This->palettes[0][i].peRed   = 0xFF;
1773         This->palettes[0][i].peGreen = 0xFF;
1774         This->palettes[0][i].peBlue  = 0xFF;
1775         This->palettes[0][i].peFlags = 0xFF;
1776     }
1777     This->currentPalette = 0;
1778
1779     /* Initialize the texture unit mapping to a 1:1 mapping */
1780     for (state = 0; state < MAX_COMBINED_SAMPLERS; ++state)
1781     {
1782         if (state < gl_info->max_fragment_samplers)
1783         {
1784             This->texUnitMap[state] = state;
1785             This->rev_tex_unit_map[state] = state;
1786         } else {
1787             This->texUnitMap[state] = WINED3D_UNMAPPED_STAGE;
1788             This->rev_tex_unit_map[state] = WINED3D_UNMAPPED_STAGE;
1789         }
1790     }
1791
1792     /* Setup the implicit swapchain. This also initializes a context. */
1793     TRACE("Creating implicit swapchain\n");
1794     hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
1795             pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
1796     if (FAILED(hr))
1797     {
1798         WARN("Failed to create implicit swapchain\n");
1799         goto err_out;
1800     }
1801
1802     This->NumberOfSwapChains = 1;
1803     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1804     if(!This->swapchains) {
1805         ERR("Out of memory!\n");
1806         goto err_out;
1807     }
1808     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1809
1810     if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1811         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1812         This->render_targets[0] = swapchain->backBuffer[0];
1813     }
1814     else {
1815         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1816         This->render_targets[0] = swapchain->frontBuffer;
1817     }
1818     IWineD3DSurface_AddRef(This->render_targets[0]);
1819
1820     /* Depth Stencil support */
1821     This->stencilBufferTarget = This->auto_depth_stencil_buffer;
1822     if (NULL != This->stencilBufferTarget) {
1823         IWineD3DSurface_AddRef(This->stencilBufferTarget);
1824     }
1825
1826     hr = This->shader_backend->shader_alloc_private(iface);
1827     if(FAILED(hr)) {
1828         TRACE("Shader private data couldn't be allocated\n");
1829         goto err_out;
1830     }
1831     hr = This->frag_pipe->alloc_private(iface);
1832     if(FAILED(hr)) {
1833         TRACE("Fragment pipeline private data couldn't be allocated\n");
1834         goto err_out;
1835     }
1836     hr = This->blitter->alloc_private(iface);
1837     if(FAILED(hr)) {
1838         TRACE("Blitter private data couldn't be allocated\n");
1839         goto err_out;
1840     }
1841
1842     /* Set up some starting GL setup */
1843
1844     /* Setup all the devices defaults */
1845     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1846     create_dummy_textures(This);
1847
1848     ENTER_GL();
1849
1850     /* Initialize the current view state */
1851     This->view_ident = 1;
1852     This->contexts[0]->last_was_rhw = 0;
1853     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1854     checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1855
1856     switch(wined3d_settings.offscreen_rendering_mode) {
1857         case ORM_FBO:
1858         case ORM_PBUFFER:
1859             This->offscreenBuffer = GL_BACK;
1860             break;
1861
1862         case ORM_BACKBUFFER:
1863         {
1864             if (context_get_current()->aux_buffers > 0)
1865             {
1866                 TRACE("Using auxilliary buffer for offscreen rendering\n");
1867                 This->offscreenBuffer = GL_AUX0;
1868             } else {
1869                 TRACE("Using back buffer for offscreen rendering\n");
1870                 This->offscreenBuffer = GL_BACK;
1871             }
1872         }
1873     }
1874
1875     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1876     LEAVE_GL();
1877
1878     /* Clear the screen */
1879     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
1880                           WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
1881                           0x00, 1.0f, 0);
1882
1883     This->d3d_initialized = TRUE;
1884
1885     if(wined3d_settings.logo) {
1886         IWineD3DDeviceImpl_LoadLogo(This, wined3d_settings.logo);
1887     }
1888     This->highest_dirty_ps_const = 0;
1889     This->highest_dirty_vs_const = 0;
1890     return WINED3D_OK;
1891
1892 err_out:
1893     HeapFree(GetProcessHeap(), 0, This->render_targets);
1894     HeapFree(GetProcessHeap(), 0, This->draw_buffers);
1895     HeapFree(GetProcessHeap(), 0, This->swapchains);
1896     This->NumberOfSwapChains = 0;
1897     if(This->palettes) {
1898         HeapFree(GetProcessHeap(), 0, This->palettes[0]);
1899         HeapFree(GetProcessHeap(), 0, This->palettes);
1900     }
1901     This->NumberOfPalettes = 0;
1902     if(swapchain) {
1903         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1904     }
1905     if(This->stateBlock) {
1906         IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->stateBlock);
1907         This->stateBlock = NULL;
1908     }
1909     if (This->blit_priv) {
1910         This->blitter->free_private(iface);
1911     }
1912     if (This->fragment_priv) {
1913         This->frag_pipe->free_private(iface);
1914     }
1915     if (This->shader_priv) {
1916         This->shader_backend->shader_free_private(iface);
1917     }
1918     return hr;
1919 }
1920
1921 static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface,
1922         WINED3DPRESENT_PARAMETERS *pPresentationParameters)
1923 {
1924     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1925     IWineD3DSwapChainImpl *swapchain = NULL;
1926     HRESULT hr;
1927
1928     /* Setup the implicit swapchain */
1929     TRACE("Creating implicit swapchain\n");
1930     hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
1931             pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
1932     if (FAILED(hr))
1933     {
1934         WARN("Failed to create implicit swapchain\n");
1935         goto err_out;
1936     }
1937
1938     This->NumberOfSwapChains = 1;
1939     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1940     if(!This->swapchains) {
1941         ERR("Out of memory!\n");
1942         goto err_out;
1943     }
1944     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1945     return WINED3D_OK;
1946
1947 err_out:
1948     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1949     return hr;
1950 }
1951
1952 static HRESULT WINAPI device_unload_resource(IWineD3DResource *resource, void *ctx)
1953 {
1954     IWineD3DResource_UnLoad(resource);
1955     IWineD3DResource_Release(resource);
1956     return WINED3D_OK;
1957 }
1958
1959 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface,
1960         D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain)
1961 {
1962     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1963     const struct wined3d_context *context;
1964     const struct wined3d_gl_info *gl_info;
1965     int sampler;
1966     UINT i;
1967     TRACE("(%p)\n", This);
1968
1969     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1970
1971     /* I don't think that the interface guarantees that the device is destroyed from the same thread
1972      * it was created. Thus make sure a context is active for the glDelete* calls
1973      */
1974     context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
1975     gl_info = context->gl_info;
1976
1977     if(This->logo_surface) IWineD3DSurface_Release(This->logo_surface);
1978
1979     /* Unload resources */
1980     IWineD3DDevice_EnumResources(iface, device_unload_resource, NULL);
1981
1982     TRACE("Deleting high order patches\n");
1983     for(i = 0; i < PATCHMAP_SIZE; i++) {
1984         struct list *e1, *e2;
1985         struct WineD3DRectPatch *patch;
1986         LIST_FOR_EACH_SAFE(e1, e2, &This->patches[i]) {
1987             patch = LIST_ENTRY(e1, struct WineD3DRectPatch, entry);
1988             IWineD3DDevice_DeletePatch(iface, patch->Handle);
1989         }
1990     }
1991
1992     /* Delete the palette conversion shader if it is around */
1993     if(This->paletteConversionShader) {
1994         ENTER_GL();
1995         GL_EXTCALL(glDeleteProgramsARB(1, &This->paletteConversionShader));
1996         LEAVE_GL();
1997         This->paletteConversionShader = 0;
1998     }
1999
2000     /* Delete the pbuffer context if there is any */
2001     if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
2002
2003     /* Delete the mouse cursor texture */
2004     if(This->cursorTexture) {
2005         ENTER_GL();
2006         glDeleteTextures(1, &This->cursorTexture);
2007         LEAVE_GL();
2008         This->cursorTexture = 0;
2009     }
2010
2011     for (sampler = 0; sampler < MAX_FRAGMENT_SAMPLERS; ++sampler) {
2012         IWineD3DDevice_SetTexture(iface, sampler, NULL);
2013     }
2014     for (sampler = 0; sampler < MAX_VERTEX_SAMPLERS; ++sampler) {
2015         IWineD3DDevice_SetTexture(iface, WINED3DVERTEXTEXTURESAMPLER0 + sampler, NULL);
2016     }
2017
2018     /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
2019      * private data, it might contain opengl pointers
2020      */
2021     if(This->depth_blt_texture) {
2022         ENTER_GL();
2023         glDeleteTextures(1, &This->depth_blt_texture);
2024         LEAVE_GL();
2025         This->depth_blt_texture = 0;
2026     }
2027     if (This->depth_blt_rb) {
2028         ENTER_GL();
2029         gl_info->fbo_ops.glDeleteRenderbuffers(1, &This->depth_blt_rb);
2030         LEAVE_GL();
2031         This->depth_blt_rb = 0;
2032         This->depth_blt_rb_w = 0;
2033         This->depth_blt_rb_h = 0;
2034     }
2035
2036     /* Release the update stateblock */
2037     if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
2038         if(This->updateStateBlock != This->stateBlock)
2039             FIXME("(%p) Something's still holding the Update stateblock\n",This);
2040     }
2041     This->updateStateBlock = NULL;
2042
2043     { /* because were not doing proper internal refcounts releasing the primary state block
2044         causes recursion with the extra checks in ResourceReleased, to avoid this we have
2045         to set this->stateBlock = NULL; first */
2046         IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
2047         This->stateBlock = NULL;
2048
2049         /* Release the stateblock */
2050         if(IWineD3DStateBlock_Release(stateBlock) > 0){
2051             FIXME("(%p) Something's still holding the Update stateblock\n",This);
2052         }
2053     }
2054
2055     /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2056     This->blitter->free_private(iface);
2057     This->frag_pipe->free_private(iface);
2058     This->shader_backend->shader_free_private(iface);
2059
2060     /* Release the buffers (with sanity checks)*/
2061     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2062     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2063         if(This->auto_depth_stencil_buffer != This->stencilBufferTarget)
2064             FIXME("(%p) Something's still holding the stencilBufferTarget\n",This);
2065     }
2066     This->stencilBufferTarget = NULL;
2067
2068     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
2069     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
2070           /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2071     }
2072     TRACE("Setting rendertarget to NULL\n");
2073     This->render_targets[0] = NULL;
2074
2075     if (This->auto_depth_stencil_buffer) {
2076         if (IWineD3DSurface_Release(This->auto_depth_stencil_buffer) > 0)
2077         {
2078             FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This);
2079         }
2080         This->auto_depth_stencil_buffer = NULL;
2081     }
2082
2083     for(i=0; i < This->NumberOfSwapChains; i++) {
2084         TRACE("Releasing the implicit swapchain %d\n", i);
2085         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
2086             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2087         }
2088     }
2089
2090     HeapFree(GetProcessHeap(), 0, This->swapchains);
2091     This->swapchains = NULL;
2092     This->NumberOfSwapChains = 0;
2093
2094     for (i = 0; i < This->NumberOfPalettes; i++) HeapFree(GetProcessHeap(), 0, This->palettes[i]);
2095     HeapFree(GetProcessHeap(), 0, This->palettes);
2096     This->palettes = NULL;
2097     This->NumberOfPalettes = 0;
2098
2099     HeapFree(GetProcessHeap(), 0, This->render_targets);
2100     HeapFree(GetProcessHeap(), 0, This->draw_buffers);
2101     This->render_targets = NULL;
2102     This->draw_buffers = NULL;
2103
2104     This->d3d_initialized = FALSE;
2105     return WINED3D_OK;
2106 }
2107
2108 static HRESULT WINAPI IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice *iface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
2109     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2110     unsigned int i;
2111
2112     for(i=0; i < This->NumberOfSwapChains; i++) {
2113         TRACE("Releasing the implicit swapchain %d\n", i);
2114         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
2115             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2116         }
2117     }
2118
2119     HeapFree(GetProcessHeap(), 0, This->swapchains);
2120     This->swapchains = NULL;
2121     This->NumberOfSwapChains = 0;
2122     return WINED3D_OK;
2123 }
2124
2125 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2126  * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2127  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2128  *
2129  * There is no way to deactivate thread safety once it is enabled.
2130  */
2131 static void WINAPI IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice *iface) {
2132     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2133
2134     /*For now just store the flag(needed in case of ddraw) */
2135     This->createParms.BehaviorFlags |= WINED3DCREATE_MULTITHREADED;
2136
2137     return;
2138 }
2139
2140 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain,
2141         const WINED3DDISPLAYMODE* pMode) {
2142     DEVMODEW devmode;
2143     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2144     LONG ret;
2145     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(pMode->Format, &This->adapter->gl_info);
2146     RECT clip_rc;
2147
2148     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2149
2150     /* Resize the screen even without a window:
2151      * The app could have unset it with SetCooperativeLevel, but not called
2152      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2153      * but we don't have any hwnd
2154      */
2155
2156     memset(&devmode, 0, sizeof(devmode));
2157     devmode.dmSize = sizeof(devmode);
2158     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2159     devmode.dmBitsPerPel = format_desc->byte_count * 8;
2160     devmode.dmPelsWidth  = pMode->Width;
2161     devmode.dmPelsHeight = pMode->Height;
2162
2163     devmode.dmDisplayFrequency = pMode->RefreshRate;
2164     if (pMode->RefreshRate != 0)  {
2165         devmode.dmFields |= DM_DISPLAYFREQUENCY;
2166     }
2167
2168     /* Only change the mode if necessary */
2169     if( (This->ddraw_width == pMode->Width) &&
2170         (This->ddraw_height == pMode->Height) &&
2171         (This->ddraw_format == pMode->Format) &&
2172         (pMode->RefreshRate == 0) ) {
2173         return WINED3D_OK;
2174     }
2175
2176     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2177     if (ret != DISP_CHANGE_SUCCESSFUL) {
2178         if(devmode.dmDisplayFrequency != 0) {
2179             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2180             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2181             devmode.dmDisplayFrequency = 0;
2182             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2183         }
2184         if(ret != DISP_CHANGE_SUCCESSFUL) {
2185             return WINED3DERR_NOTAVAILABLE;
2186         }
2187     }
2188
2189     /* Store the new values */
2190     This->ddraw_width = pMode->Width;
2191     This->ddraw_height = pMode->Height;
2192     This->ddraw_format = pMode->Format;
2193
2194     /* And finally clip mouse to our screen */
2195     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2196     ClipCursor(&clip_rc);
2197
2198     return WINED3D_OK;
2199 }
2200
2201 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2202    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2203    *ppD3D= This->wineD3D;
2204    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2205    IWineD3D_AddRef(*ppD3D);
2206    return WINED3D_OK;
2207 }
2208
2209 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2210     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2211
2212     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2213          (This->adapter->TextureRam/(1024*1024)),
2214          ((This->adapter->TextureRam - This->adapter->UsedTextureRam) / (1024*1024)));
2215     /* return simulated texture memory left */
2216     return (This->adapter->TextureRam - This->adapter->UsedTextureRam);
2217 }
2218
2219 /*****
2220  * Get / Set Stream Source
2221  *****/
2222 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,
2223         IWineD3DBuffer *pStreamData, UINT OffsetInBytes, UINT Stride)
2224 {
2225     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2226     IWineD3DBuffer *oldSrc;
2227
2228     if (StreamNumber >= MAX_STREAMS) {
2229         WARN("Stream out of range %d\n", StreamNumber);
2230         return WINED3DERR_INVALIDCALL;
2231     } else if(OffsetInBytes & 0x3) {
2232         WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes);
2233         return WINED3DERR_INVALIDCALL;
2234     }
2235
2236     oldSrc = This->updateStateBlock->streamSource[StreamNumber];
2237     TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
2238
2239     This->updateStateBlock->changed.streamSource |= 1 << StreamNumber;
2240
2241     if(oldSrc == pStreamData &&
2242        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2243        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
2244        TRACE("Application is setting the old values over, nothing to do\n");
2245        return WINED3D_OK;
2246     }
2247
2248     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2249     if (pStreamData) {
2250         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
2251         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
2252     }
2253
2254     /* Handle recording of state blocks */
2255     if (This->isRecordingState) {
2256         TRACE("Recording... not performing anything\n");
2257         if (pStreamData) IWineD3DBuffer_AddRef(pStreamData);
2258         if (oldSrc) IWineD3DBuffer_Release(oldSrc);
2259         return WINED3D_OK;
2260     }
2261
2262     if (pStreamData != NULL) {
2263         InterlockedIncrement(&((struct wined3d_buffer *)pStreamData)->bind_count);
2264         IWineD3DBuffer_AddRef(pStreamData);
2265     }
2266     if (oldSrc != NULL) {
2267         InterlockedDecrement(&((struct wined3d_buffer *)oldSrc)->bind_count);
2268         IWineD3DBuffer_Release(oldSrc);
2269     }
2270
2271     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2272
2273     return WINED3D_OK;
2274 }
2275
2276 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface,
2277         UINT StreamNumber, IWineD3DBuffer **pStream, UINT *pOffset, UINT *pStride)
2278 {
2279     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2280
2281     TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This, StreamNumber,
2282            This->stateBlock->streamSource[StreamNumber],
2283            This->stateBlock->streamOffset[StreamNumber],
2284            This->stateBlock->streamStride[StreamNumber]);
2285
2286     if (StreamNumber >= MAX_STREAMS) {
2287         WARN("Stream out of range %d\n", StreamNumber);
2288         return WINED3DERR_INVALIDCALL;
2289     }
2290     *pStream = This->stateBlock->streamSource[StreamNumber];
2291     *pStride = This->stateBlock->streamStride[StreamNumber];
2292     if (pOffset) {
2293         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2294     }
2295
2296     if (*pStream != NULL) {
2297         IWineD3DBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2298     }
2299     return WINED3D_OK;
2300 }
2301
2302 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2303     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2304     UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2305     UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2306
2307     /* Verify input at least in d3d9 this is invalid*/
2308     if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (Divider & WINED3DSTREAMSOURCE_INDEXEDDATA)){
2309         WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2310         return WINED3DERR_INVALIDCALL;
2311     }
2312     if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && StreamNumber == 0 ){
2313         WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2314         return WINED3DERR_INVALIDCALL;
2315     }
2316     if( Divider == 0 ){
2317         WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2318         return WINED3DERR_INVALIDCALL;
2319     }
2320
2321     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2322     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2323
2324     This->updateStateBlock->changed.streamFreq |= 1 << StreamNumber;
2325     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2326
2327     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2328        This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2329         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2330     }
2331
2332     return WINED3D_OK;
2333 }
2334
2335 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2336     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2337
2338     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2339     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2340
2341     TRACE("(%p) : returning %d\n", This, *Divider);
2342
2343     return WINED3D_OK;
2344 }
2345
2346 /*****
2347  * Get / Set & Multiply Transform
2348  *****/
2349 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2350     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2351
2352     /* Most of this routine, comments included copied from ddraw tree initially: */
2353     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2354
2355     /* Handle recording of state blocks */
2356     if (This->isRecordingState) {
2357         TRACE("Recording... not performing anything\n");
2358         This->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
2359         This->updateStateBlock->transforms[d3dts] = *lpmatrix;
2360         return WINED3D_OK;
2361     }
2362
2363     /*
2364      * If the new matrix is the same as the current one,
2365      * we cut off any further processing. this seems to be a reasonable
2366      * optimization because as was noticed, some apps (warcraft3 for example)
2367      * tend towards setting the same matrix repeatedly for some reason.
2368      *
2369      * From here on we assume that the new matrix is different, wherever it matters.
2370      */
2371     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2372         TRACE("The app is setting the same matrix over again\n");
2373         return WINED3D_OK;
2374     } else {
2375         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2376     }
2377
2378     /*
2379        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2380        where ViewMat = Camera space, WorldMat = world space.
2381
2382        In OpenGL, camera and world space is combined into GL_MODELVIEW
2383        matrix.  The Projection matrix stay projection matrix.
2384      */
2385
2386     /* Capture the times we can just ignore the change for now */
2387     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrix */
2388         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2389         /* Handled by the state manager */
2390     }
2391
2392     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2393     return WINED3D_OK;
2394
2395 }
2396 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2397     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2398     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2399     *pMatrix = This->stateBlock->transforms[State];
2400     return WINED3D_OK;
2401 }
2402
2403 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2404     const WINED3DMATRIX *mat = NULL;
2405     WINED3DMATRIX temp;
2406
2407     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2408      * below means it will be recorded in a state block change, but it
2409      * works regardless where it is recorded.
2410      * If this is found to be wrong, change to StateBlock.
2411      */
2412     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2413     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2414
2415     if (State <= HIGHEST_TRANSFORMSTATE)
2416     {
2417         mat = &This->updateStateBlock->transforms[State];
2418     } else {
2419         FIXME("Unhandled transform state!!\n");
2420     }
2421
2422     multiply_matrix(&temp, mat, pMatrix);
2423
2424     /* Apply change via set transform - will reapply to eg. lights this way */
2425     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2426 }
2427
2428 /*****
2429  * Get / Set Light
2430  *****/
2431 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2432    you can reference any indexes you want as long as that number max are enabled at any
2433    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2434    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2435    but when recording, just build a chain pretty much of commands to be replayed.                  */
2436
2437 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2438     float rho;
2439     struct wined3d_light_info *object = NULL;
2440     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2441     struct list *e;
2442
2443     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2444     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2445
2446     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2447      * the gl driver.
2448      */
2449     if(!pLight) {
2450         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2451         return WINED3DERR_INVALIDCALL;
2452     }
2453
2454     switch(pLight->Type) {
2455         case WINED3DLIGHT_POINT:
2456         case WINED3DLIGHT_SPOT:
2457         case WINED3DLIGHT_PARALLELPOINT:
2458         case WINED3DLIGHT_GLSPOT:
2459             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2460              * most wanted
2461              */
2462             if (pLight->Attenuation0 < 0.0f || pLight->Attenuation1 < 0.0f || pLight->Attenuation2 < 0.0f)
2463             {
2464                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2465                 return WINED3DERR_INVALIDCALL;
2466             }
2467             break;
2468
2469         case WINED3DLIGHT_DIRECTIONAL:
2470             /* Ignores attenuation */
2471             break;
2472
2473         default:
2474         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2475         return WINED3DERR_INVALIDCALL;
2476     }
2477
2478     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi])
2479     {
2480         object = LIST_ENTRY(e, struct wined3d_light_info, entry);
2481         if(object->OriginalIndex == Index) break;
2482         object = NULL;
2483     }
2484
2485     if(!object) {
2486         TRACE("Adding new light\n");
2487         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2488         if(!object) {
2489             ERR("Out of memory error when allocating a light\n");
2490             return E_OUTOFMEMORY;
2491         }
2492         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2493         object->glIndex = -1;
2494         object->OriginalIndex = Index;
2495     }
2496
2497     /* Initialize the object */
2498     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,
2499           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2500           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2501           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2502     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2503           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2504     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2505
2506     /* Save away the information */
2507     object->OriginalParms = *pLight;
2508
2509     switch (pLight->Type) {
2510     case WINED3DLIGHT_POINT:
2511         /* Position */
2512         object->lightPosn[0] = pLight->Position.x;
2513         object->lightPosn[1] = pLight->Position.y;
2514         object->lightPosn[2] = pLight->Position.z;
2515         object->lightPosn[3] = 1.0f;
2516         object->cutoff = 180.0f;
2517         /* FIXME: Range */
2518         break;
2519
2520     case WINED3DLIGHT_DIRECTIONAL:
2521         /* Direction */
2522         object->lightPosn[0] = -pLight->Direction.x;
2523         object->lightPosn[1] = -pLight->Direction.y;
2524         object->lightPosn[2] = -pLight->Direction.z;
2525         object->lightPosn[3] = 0.0f;
2526         object->exponent     = 0.0f;
2527         object->cutoff       = 180.0f;
2528         break;
2529
2530     case WINED3DLIGHT_SPOT:
2531         /* Position */
2532         object->lightPosn[0] = pLight->Position.x;
2533         object->lightPosn[1] = pLight->Position.y;
2534         object->lightPosn[2] = pLight->Position.z;
2535         object->lightPosn[3] = 1.0f;
2536
2537         /* Direction */
2538         object->lightDirn[0] = pLight->Direction.x;
2539         object->lightDirn[1] = pLight->Direction.y;
2540         object->lightDirn[2] = pLight->Direction.z;
2541         object->lightDirn[3] = 1.0f;
2542
2543         /*
2544          * opengl-ish and d3d-ish spot lights use too different models for the
2545          * light "intensity" as a function of the angle towards the main light direction,
2546          * so we only can approximate very roughly.
2547          * however spot lights are rather rarely used in games (if ever used at all).
2548          * furthermore if still used, probably nobody pays attention to such details.
2549          */
2550         if (pLight->Falloff == 0) {
2551             /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2552              * falloff resp. exponent parameter as an exponent, so the spot light lighting
2553              * will always be 1.0 for both of them, and we don't have to care for the
2554              * rest of the rather complex calculation
2555              */
2556             object->exponent = 0.0f;
2557         } else {
2558             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2559             if (rho < 0.0001f) rho = 0.0001f;
2560             object->exponent = -0.3f/logf(cosf(rho/2));
2561         }
2562         if (object->exponent > 128.0f)
2563         {
2564             object->exponent = 128.0f;
2565         }
2566         object->cutoff = pLight->Phi*90/M_PI;
2567
2568         /* FIXME: Range */
2569         break;
2570
2571     default:
2572         FIXME("Unrecognized light type %d\n", pLight->Type);
2573     }
2574
2575     /* Update the live definitions if the light is currently assigned a glIndex */
2576     if (object->glIndex != -1 && !This->isRecordingState) {
2577         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2578     }
2579     return WINED3D_OK;
2580 }
2581
2582 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT *pLight)
2583 {
2584     struct wined3d_light_info *lightInfo = NULL;
2585     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2586     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2587     struct list *e;
2588     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2589
2590     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi])
2591     {
2592         lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2593         if(lightInfo->OriginalIndex == Index) break;
2594         lightInfo = NULL;
2595     }
2596
2597     if (lightInfo == NULL) {
2598         TRACE("Light information requested but light not defined\n");
2599         return WINED3DERR_INVALIDCALL;
2600     }
2601
2602     *pLight = lightInfo->OriginalParms;
2603     return WINED3D_OK;
2604 }
2605
2606 /*****
2607  * Get / Set Light Enable
2608  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2609  *****/
2610 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable)
2611 {
2612     struct wined3d_light_info *lightInfo = NULL;
2613     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2614     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2615     struct list *e;
2616     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2617
2618     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi])
2619     {
2620         lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2621         if(lightInfo->OriginalIndex == Index) break;
2622         lightInfo = NULL;
2623     }
2624     TRACE("Found light: %p\n", lightInfo);
2625
2626     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2627     if (lightInfo == NULL) {
2628
2629         TRACE("Light enabled requested but light not defined, so defining one!\n");
2630         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2631
2632         /* Search for it again! Should be fairly quick as near head of list */
2633         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi])
2634         {
2635             lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2636             if(lightInfo->OriginalIndex == Index) break;
2637             lightInfo = NULL;
2638         }
2639         if (lightInfo == NULL) {
2640             FIXME("Adding default lights has failed dismally\n");
2641             return WINED3DERR_INVALIDCALL;
2642         }
2643     }
2644
2645     if(!Enable) {
2646         if(lightInfo->glIndex != -1) {
2647             if(!This->isRecordingState) {
2648                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2649             }
2650
2651             This->updateStateBlock->activeLights[lightInfo->glIndex] = NULL;
2652             lightInfo->glIndex = -1;
2653         } else {
2654             TRACE("Light already disabled, nothing to do\n");
2655         }
2656         lightInfo->enabled = FALSE;
2657     } else {
2658         lightInfo->enabled = TRUE;
2659         if (lightInfo->glIndex != -1) {
2660             /* nop */
2661             TRACE("Nothing to do as light was enabled\n");
2662         } else {
2663             int i;
2664             /* Find a free gl light */
2665             for(i = 0; i < This->maxConcurrentLights; i++) {
2666                 if(This->updateStateBlock->activeLights[i] == NULL) {
2667                     This->updateStateBlock->activeLights[i] = lightInfo;
2668                     lightInfo->glIndex = i;
2669                     break;
2670                 }
2671             }
2672             if(lightInfo->glIndex == -1) {
2673                 /* Our tests show that Windows returns D3D_OK in this situation, even with
2674                  * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2675                  * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2676                  * as well for those lights.
2677                  *
2678                  * TODO: Test how this affects rendering
2679                  */
2680                 WARN("Too many concurrently active lights\n");
2681                 return WINED3D_OK;
2682             }
2683
2684             /* i == lightInfo->glIndex */
2685             if(!This->isRecordingState) {
2686                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2687             }
2688         }
2689     }
2690
2691     return WINED3D_OK;
2692 }
2693
2694 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable)
2695 {
2696     struct wined3d_light_info *lightInfo = NULL;
2697     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2698     struct list *e;
2699     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2700     TRACE("(%p) : for idx(%d)\n", This, Index);
2701
2702     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi])
2703     {
2704         lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2705         if(lightInfo->OriginalIndex == Index) break;
2706         lightInfo = NULL;
2707     }
2708
2709     if (lightInfo == NULL) {
2710         TRACE("Light enabled state requested but light not defined\n");
2711         return WINED3DERR_INVALIDCALL;
2712     }
2713     /* true is 128 according to SetLightEnable */
2714     *pEnable = lightInfo->enabled ? 128 : 0;
2715     return WINED3D_OK;
2716 }
2717
2718 /*****
2719  * Get / Set Clip Planes
2720  *****/
2721 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2722     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2723     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2724
2725     /* Validate Index */
2726     if (Index >= This->adapter->gl_info.max_clipplanes)
2727     {
2728         TRACE("Application has requested clipplane this device doesn't support\n");
2729         return WINED3DERR_INVALIDCALL;
2730     }
2731
2732     This->updateStateBlock->changed.clipplane |= 1 << Index;
2733
2734     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2735        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2736        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2737        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2738         TRACE("Application is setting old values over, nothing to do\n");
2739         return WINED3D_OK;
2740     }
2741
2742     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2743     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2744     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2745     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2746
2747     /* Handle recording of state blocks */
2748     if (This->isRecordingState) {
2749         TRACE("Recording... not performing anything\n");
2750         return WINED3D_OK;
2751     }
2752
2753     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2754
2755     return WINED3D_OK;
2756 }
2757
2758 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2759     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2760     TRACE("(%p) : for idx %d\n", This, Index);
2761
2762     /* Validate Index */
2763     if (Index >= This->adapter->gl_info.max_clipplanes)
2764     {
2765         TRACE("Application has requested clipplane this device doesn't support\n");
2766         return WINED3DERR_INVALIDCALL;
2767     }
2768
2769     pPlane[0] = This->stateBlock->clipplane[Index][0];
2770     pPlane[1] = This->stateBlock->clipplane[Index][1];
2771     pPlane[2] = This->stateBlock->clipplane[Index][2];
2772     pPlane[3] = This->stateBlock->clipplane[Index][3];
2773     return WINED3D_OK;
2774 }
2775
2776 /*****
2777  * Get / Set Clip Plane Status
2778  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2779  *****/
2780 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2781     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2782     FIXME("(%p) : stub\n", This);
2783     if (NULL == pClipStatus) {
2784       return WINED3DERR_INVALIDCALL;
2785     }
2786     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2787     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2788     return WINED3D_OK;
2789 }
2790
2791 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2792     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2793     FIXME("(%p) : stub\n", This);
2794     if (NULL == pClipStatus) {
2795       return WINED3DERR_INVALIDCALL;
2796     }
2797     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2798     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2799     return WINED3D_OK;
2800 }
2801
2802 /*****
2803  * Get / Set Material
2804  *****/
2805 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2806     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2807
2808     This->updateStateBlock->changed.material = TRUE;
2809     This->updateStateBlock->material = *pMaterial;
2810
2811     /* Handle recording of state blocks */
2812     if (This->isRecordingState) {
2813         TRACE("Recording... not performing anything\n");
2814         return WINED3D_OK;
2815     }
2816
2817     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_MATERIAL);
2818     return WINED3D_OK;
2819 }
2820
2821 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2822     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2823     *pMaterial = This->updateStateBlock->material;
2824     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2825         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2826     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2827         pMaterial->Ambient.b, pMaterial->Ambient.a);
2828     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2829         pMaterial->Specular.b, pMaterial->Specular.a);
2830     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2831         pMaterial->Emissive.b, pMaterial->Emissive.a);
2832     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2833
2834     return WINED3D_OK;
2835 }
2836
2837 /*****
2838  * Get / Set Indices
2839  *****/
2840 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndexBuffer(IWineD3DDevice *iface,
2841         IWineD3DBuffer *pIndexData, WINED3DFORMAT fmt)
2842 {
2843     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2844     IWineD3DBuffer *oldIdxs;
2845
2846     TRACE("(%p) : Setting to %p\n", This, pIndexData);
2847     oldIdxs = This->updateStateBlock->pIndexData;
2848
2849     This->updateStateBlock->changed.indices = TRUE;
2850     This->updateStateBlock->pIndexData = pIndexData;
2851     This->updateStateBlock->IndexFmt = fmt;
2852
2853     /* Handle recording of state blocks */
2854     if (This->isRecordingState) {
2855         TRACE("Recording... not performing anything\n");
2856         if(pIndexData) IWineD3DBuffer_AddRef(pIndexData);
2857         if(oldIdxs) IWineD3DBuffer_Release(oldIdxs);
2858         return WINED3D_OK;
2859     }
2860
2861     if(oldIdxs != pIndexData) {
2862         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2863         if(pIndexData) {
2864             InterlockedIncrement(&((struct wined3d_buffer *)pIndexData)->bind_count);
2865             IWineD3DBuffer_AddRef(pIndexData);
2866         }
2867         if(oldIdxs) {
2868             InterlockedDecrement(&((struct wined3d_buffer *)oldIdxs)->bind_count);
2869             IWineD3DBuffer_Release(oldIdxs);
2870         }
2871     }
2872
2873     return WINED3D_OK;
2874 }
2875
2876 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndexBuffer(IWineD3DDevice *iface, IWineD3DBuffer **ppIndexData)
2877 {
2878     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2879
2880     *ppIndexData = This->stateBlock->pIndexData;
2881
2882     /* up ref count on ppindexdata */
2883     if (*ppIndexData) {
2884         IWineD3DBuffer_AddRef(*ppIndexData);
2885         TRACE("(%p) index data set to %p\n", This, ppIndexData);
2886     }else{
2887         TRACE("(%p) No index data set\n", This);
2888     }
2889     TRACE("Returning %p\n", *ppIndexData);
2890
2891     return WINED3D_OK;
2892 }
2893
2894 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2895 static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, INT BaseIndex) {
2896     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2897     TRACE("(%p)->(%d)\n", This, BaseIndex);
2898
2899     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2900         TRACE("Application is setting the old value over, nothing to do\n");
2901         return WINED3D_OK;
2902     }
2903
2904     This->updateStateBlock->baseVertexIndex = BaseIndex;
2905
2906     if (This->isRecordingState) {
2907         TRACE("Recording... not performing anything\n");
2908         return WINED3D_OK;
2909     }
2910     /* The base vertex index affects the stream sources */
2911     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2912     return WINED3D_OK;
2913 }
2914
2915 static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, INT* base_index) {
2916     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2917     TRACE("(%p) : base_index %p\n", This, base_index);
2918
2919     *base_index = This->stateBlock->baseVertexIndex;
2920
2921     TRACE("Returning %u\n", *base_index);
2922
2923     return WINED3D_OK;
2924 }
2925
2926 /*****
2927  * Get / Set Viewports
2928  *****/
2929 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2930     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2931
2932     TRACE("(%p)\n", This);
2933     This->updateStateBlock->changed.viewport = TRUE;
2934     This->updateStateBlock->viewport = *pViewport;
2935
2936     /* Handle recording of state blocks */
2937     if (This->isRecordingState) {
2938         TRACE("Recording... not performing anything\n");
2939         return WINED3D_OK;
2940     }
2941
2942     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2943           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2944
2945     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2946     return WINED3D_OK;
2947
2948 }
2949
2950 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2951     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2952     TRACE("(%p)\n", This);
2953     *pViewport = This->stateBlock->viewport;
2954     return WINED3D_OK;
2955 }
2956
2957 /*****
2958  * Get / Set Render States
2959  * TODO: Verify against dx9 definitions
2960  *****/
2961 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2962
2963     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2964     DWORD oldValue = This->stateBlock->renderState[State];
2965
2966     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2967
2968     This->updateStateBlock->changed.renderState[State >> 5] |= 1 << (State & 0x1f);
2969     This->updateStateBlock->renderState[State] = Value;
2970
2971     /* Handle recording of state blocks */
2972     if (This->isRecordingState) {
2973         TRACE("Recording... not performing anything\n");
2974         return WINED3D_OK;
2975     }
2976
2977     /* Compared here and not before the assignment to allow proper stateblock recording */
2978     if(Value == oldValue) {
2979         TRACE("Application is setting the old value over, nothing to do\n");
2980     } else {
2981         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
2982     }
2983
2984     return WINED3D_OK;
2985 }
2986
2987 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
2988     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2989     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
2990     *pValue = This->stateBlock->renderState[State];
2991     return WINED3D_OK;
2992 }
2993
2994 /*****
2995  * Get / Set Sampler States
2996  * TODO: Verify against dx9 definitions
2997  *****/
2998
2999 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3000     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3001     DWORD oldValue;
3002
3003     TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3004             This, Sampler, debug_d3dsamplerstate(Type), Type, Value);
3005
3006     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3007         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3008     }
3009
3010     if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) {
3011         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3012         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3013     }
3014     /**
3015     * SetSampler is designed to allow for more than the standard up to 8 textures
3016     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3017     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3018     *
3019     * http://developer.nvidia.com/object/General_FAQ.html#t6
3020     *
3021     * There are two new settings for GForce
3022     * the sampler one:
3023     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3024     * and the texture one:
3025     * GL_MAX_TEXTURE_COORDS_ARB.
3026     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3027      ******************/
3028
3029     oldValue = This->stateBlock->samplerState[Sampler][Type];
3030     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3031     This->updateStateBlock->changed.samplerState[Sampler] |= 1 << Type;
3032
3033     /* Handle recording of state blocks */
3034     if (This->isRecordingState) {
3035         TRACE("Recording... not performing anything\n");
3036         return WINED3D_OK;
3037     }
3038
3039     if(oldValue == Value) {
3040         TRACE("Application is setting the old value over, nothing to do\n");
3041         return WINED3D_OK;
3042     }
3043
3044     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3045
3046     return WINED3D_OK;
3047 }
3048
3049 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3050     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3051
3052     TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3053             This, Sampler, debug_d3dsamplerstate(Type), Type);
3054
3055     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3056         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3057     }
3058
3059     if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) {
3060         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3061         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3062     }
3063     *Value = This->stateBlock->samplerState[Sampler][Type];
3064     TRACE("(%p) : Returning %#x\n", This, *Value);
3065
3066     return WINED3D_OK;
3067 }
3068
3069 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3070     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3071
3072     This->updateStateBlock->changed.scissorRect = TRUE;
3073     if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
3074         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
3075         return WINED3D_OK;
3076     }
3077     CopyRect(&This->updateStateBlock->scissorRect, pRect);
3078
3079     if(This->isRecordingState) {
3080         TRACE("Recording... not performing anything\n");
3081         return WINED3D_OK;
3082     }
3083
3084     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
3085
3086     return WINED3D_OK;
3087 }
3088
3089 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3090     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3091
3092     *pRect = This->updateStateBlock->scissorRect;
3093     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3094     return WINED3D_OK;
3095 }
3096
3097 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3098     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3099     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3100
3101     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3102
3103     if (pDecl) IWineD3DVertexDeclaration_AddRef(pDecl);
3104     if (oldDecl) IWineD3DVertexDeclaration_Release(oldDecl);
3105
3106     This->updateStateBlock->vertexDecl = pDecl;
3107     This->updateStateBlock->changed.vertexDecl = TRUE;
3108
3109     if (This->isRecordingState) {
3110         TRACE("Recording... not performing anything\n");
3111         return WINED3D_OK;
3112     } else if(pDecl == oldDecl) {
3113         /* Checked after the assignment to allow proper stateblock recording */
3114         TRACE("Application is setting the old declaration over, nothing to do\n");
3115         return WINED3D_OK;
3116     }
3117
3118     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3119     return WINED3D_OK;
3120 }
3121
3122 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3124
3125     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3126
3127     *ppDecl = This->stateBlock->vertexDecl;
3128     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3129     return WINED3D_OK;
3130 }
3131
3132 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3133     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3134     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3135
3136     This->updateStateBlock->vertexShader         = pShader;
3137     This->updateStateBlock->changed.vertexShader = TRUE;
3138
3139     if (This->isRecordingState) {
3140         if(pShader) IWineD3DVertexShader_AddRef(pShader);
3141         if(oldShader) IWineD3DVertexShader_Release(oldShader);
3142         TRACE("Recording... not performing anything\n");
3143         return WINED3D_OK;
3144     } else if(oldShader == pShader) {
3145         /* Checked here to allow proper stateblock recording */
3146         TRACE("App is setting the old shader over, nothing to do\n");
3147         return WINED3D_OK;
3148     }
3149
3150     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3151     if(pShader) IWineD3DVertexShader_AddRef(pShader);
3152     if(oldShader) IWineD3DVertexShader_Release(oldShader);
3153
3154     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3155
3156     return WINED3D_OK;
3157 }
3158
3159 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3160     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3161
3162     if (NULL == ppShader) {
3163         return WINED3DERR_INVALIDCALL;
3164     }
3165     *ppShader = This->stateBlock->vertexShader;
3166     if( NULL != *ppShader)
3167         IWineD3DVertexShader_AddRef(*ppShader);
3168
3169     TRACE("(%p) : returning %p\n", This, *ppShader);
3170     return WINED3D_OK;
3171 }
3172
3173 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3174     IWineD3DDevice *iface,
3175     UINT start,
3176     CONST BOOL *srcData,
3177     UINT count) {
3178
3179     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3180     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3181
3182     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3183             iface, srcData, start, count);
3184
3185     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3186
3187     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3188     for (i = 0; i < cnt; i++)
3189         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3190
3191     for (i = start; i < cnt + start; ++i) {
3192         This->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
3193     }
3194
3195     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3196
3197     return WINED3D_OK;
3198 }
3199
3200 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3201     IWineD3DDevice *iface,
3202     UINT start,
3203     BOOL *dstData,
3204     UINT count) {
3205
3206     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3207     int cnt = min(count, MAX_CONST_B - start);
3208
3209     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3210             iface, dstData, start, count);
3211
3212     if (dstData == NULL || cnt < 0)
3213         return WINED3DERR_INVALIDCALL;
3214
3215     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3216     return WINED3D_OK;
3217 }
3218
3219 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3220     IWineD3DDevice *iface,
3221     UINT start,
3222     CONST int *srcData,
3223     UINT count) {
3224
3225     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3226     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3227
3228     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3229             iface, srcData, start, count);
3230
3231     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3232
3233     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3234     for (i = 0; i < cnt; i++)
3235         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3236            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3237
3238     for (i = start; i < cnt + start; ++i) {
3239         This->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
3240     }
3241
3242     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3243
3244     return WINED3D_OK;
3245 }
3246
3247 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3248     IWineD3DDevice *iface,
3249     UINT start,
3250     int *dstData,
3251     UINT count) {
3252
3253     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3254     int cnt = min(count, MAX_CONST_I - start);
3255
3256     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3257             iface, dstData, start, count);
3258
3259     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3260         return WINED3DERR_INVALIDCALL;
3261
3262     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3263     return WINED3D_OK;
3264 }
3265
3266 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3267     IWineD3DDevice *iface,
3268     UINT start,
3269     CONST float *srcData,
3270     UINT count) {
3271
3272     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3273     UINT i;
3274
3275     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3276             iface, srcData, start, count);
3277
3278     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3279     if (srcData == NULL || start + count > This->d3d_vshader_constantF || start > This->d3d_vshader_constantF)
3280         return WINED3DERR_INVALIDCALL;
3281
3282     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3283     if(TRACE_ON(d3d)) {
3284         for (i = 0; i < count; i++)
3285             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3286                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3287     }
3288
3289     if (!This->isRecordingState)
3290     {
3291         This->shader_backend->shader_update_float_vertex_constants(iface, start, count);
3292         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3293     }
3294
3295     memset(This->updateStateBlock->changed.vertexShaderConstantsF + start, 1,
3296             sizeof(*This->updateStateBlock->changed.vertexShaderConstantsF) * count);
3297
3298     return WINED3D_OK;
3299 }
3300
3301 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3302     IWineD3DDevice *iface,
3303     UINT start,
3304     float *dstData,
3305     UINT count) {
3306
3307     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3308     int cnt = min(count, This->d3d_vshader_constantF - start);
3309
3310     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3311             iface, dstData, start, count);
3312
3313     if (dstData == NULL || cnt < 0)
3314         return WINED3DERR_INVALIDCALL;
3315
3316     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3317     return WINED3D_OK;
3318 }
3319
3320 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3321     DWORD i;
3322     for(i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
3323     {
3324         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3325     }
3326 }
3327
3328 static void device_map_stage(IWineD3DDeviceImpl *This, DWORD stage, DWORD unit)
3329 {
3330     DWORD i = This->rev_tex_unit_map[unit];
3331     DWORD j = This->texUnitMap[stage];
3332
3333     This->texUnitMap[stage] = unit;
3334     if (i != WINED3D_UNMAPPED_STAGE && i != stage)
3335     {
3336         This->texUnitMap[i] = WINED3D_UNMAPPED_STAGE;
3337     }
3338
3339     This->rev_tex_unit_map[unit] = stage;
3340     if (j != WINED3D_UNMAPPED_STAGE && j != unit)
3341     {
3342         This->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE;
3343     }
3344 }
3345
3346 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
3347     int i;
3348
3349     This->fixed_function_usage_map = 0;
3350     for (i = 0; i < MAX_TEXTURES; ++i) {
3351         WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP];
3352         WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP];
3353         DWORD color_arg1 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG1] & WINED3DTA_SELECTMASK;
3354         DWORD color_arg2 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG2] & WINED3DTA_SELECTMASK;
3355         DWORD color_arg3 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG0] & WINED3DTA_SELECTMASK;
3356         DWORD alpha_arg1 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1] & WINED3DTA_SELECTMASK;
3357         DWORD alpha_arg2 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2] & WINED3DTA_SELECTMASK;
3358         DWORD alpha_arg3 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0] & WINED3DTA_SELECTMASK;
3359
3360         if (color_op == WINED3DTOP_DISABLE) {
3361             /* Not used, and disable higher stages */
3362             break;
3363         }
3364
3365         if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG2)
3366                 || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG1)
3367                 || ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP))
3368                 || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
3369                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
3370                 || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
3371             This->fixed_function_usage_map |= (1 << i);
3372         }
3373
3374         if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
3375             This->fixed_function_usage_map |= (1 << (i + 1));
3376         }
3377     }
3378 }
3379
3380 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
3381     unsigned int i, tex;
3382     WORD ffu_map;
3383
3384     device_update_fixed_function_usage_map(This);
3385     ffu_map = This->fixed_function_usage_map;
3386
3387     if (This->max_ffp_textures == This->max_ffp_texture_stages ||
3388             This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
3389         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3390         {
3391             if (!(ffu_map & 1)) continue;
3392
3393             if (This->texUnitMap[i] != i) {
3394                 device_map_stage(This, i, i);
3395                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3396                 markTextureStagesDirty(This, i);
3397             }
3398         }
3399         return;
3400     }
3401
3402     /* Now work out the mapping */
3403     tex = 0;
3404     for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3405     {
3406         if (!(ffu_map & 1)) continue;
3407
3408         if (This->texUnitMap[i] != tex) {
3409             device_map_stage(This, i, tex);
3410             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3411             markTextureStagesDirty(This, i);
3412         }
3413
3414         ++tex;
3415     }
3416 }
3417
3418 static void device_map_psamplers(IWineD3DDeviceImpl *This) {
3419     const WINED3DSAMPLER_TEXTURE_TYPE *sampler_type =
3420             ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.sampler_type;
3421     unsigned int i;
3422
3423     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
3424         if (sampler_type[i] && This->texUnitMap[i] != i)
3425         {
3426             device_map_stage(This, i, i);
3427             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3428             if (i < MAX_TEXTURES) {
3429                 markTextureStagesDirty(This, i);
3430             }
3431         }
3432     }
3433 }
3434
3435 static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshader_sampler_tokens,
3436         const DWORD *vshader_sampler_tokens, DWORD unit)
3437 {
3438     DWORD current_mapping = This->rev_tex_unit_map[unit];
3439
3440     /* Not currently used */
3441     if (current_mapping == WINED3D_UNMAPPED_STAGE) return TRUE;
3442
3443     if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
3444         /* Used by a fragment sampler */
3445
3446         if (!pshader_sampler_tokens) {
3447             /* No pixel shader, check fixed function */
3448             return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping));
3449         }
3450
3451         /* Pixel shader, check the shader's sampler map */
3452         return !pshader_sampler_tokens[current_mapping];
3453     }
3454
3455     /* Used by a vertex sampler */
3456     return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS];
3457 }
3458
3459 static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
3460     const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_type =
3461             ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.sampler_type;
3462     const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_type = NULL;
3463     int start = min(MAX_COMBINED_SAMPLERS, This->adapter->gl_info.max_combined_samplers) - 1;
3464     int i;
3465
3466     if (ps) {
3467         IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
3468
3469         /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3470          * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3471         pshader_sampler_type = pshader->baseShader.reg_maps.sampler_type;
3472     }
3473
3474     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
3475         DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
3476         if (vshader_sampler_type[i])
3477         {
3478             if (This->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
3479             {
3480                 /* Already mapped somewhere */
3481                 continue;
3482             }
3483
3484             while (start >= 0) {
3485                 if (device_unit_free_for_vs(This, pshader_sampler_type, vshader_sampler_type, start))
3486                 {
3487                     device_map_stage(This, vsampler_idx, start);
3488                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx));
3489
3490                     --start;
3491                     break;
3492                 }
3493
3494                 --start;
3495             }
3496         }
3497     }
3498 }
3499
3500 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3501     BOOL vs = use_vs(This->stateBlock);
3502     BOOL ps = use_ps(This->stateBlock);
3503     /*
3504      * Rules are:
3505      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3506      * that would be really messy and require shader recompilation
3507      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3508      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3509      */
3510     if (ps) {
3511         device_map_psamplers(This);
3512     } else {
3513         device_map_fixed_function_samplers(This);
3514     }
3515
3516     if (vs) {
3517         device_map_vsamplers(This, ps);
3518     }
3519 }
3520
3521 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3522     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3523     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3524     This->updateStateBlock->pixelShader         = pShader;
3525     This->updateStateBlock->changed.pixelShader = TRUE;
3526
3527     /* Handle recording of state blocks */
3528     if (This->isRecordingState) {
3529         TRACE("Recording... not performing anything\n");
3530     }
3531
3532     if (This->isRecordingState) {
3533         TRACE("Recording... not performing anything\n");
3534         if(pShader) IWineD3DPixelShader_AddRef(pShader);
3535         if(oldShader) IWineD3DPixelShader_Release(oldShader);
3536         return WINED3D_OK;
3537     }
3538
3539     if(pShader == oldShader) {
3540         TRACE("App is setting the old pixel shader over, nothing to do\n");
3541         return WINED3D_OK;
3542     }
3543
3544     if(pShader) IWineD3DPixelShader_AddRef(pShader);
3545     if(oldShader) IWineD3DPixelShader_Release(oldShader);
3546
3547     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3548     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3549
3550     return WINED3D_OK;
3551 }
3552
3553 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3554     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3555
3556     if (NULL == ppShader) {
3557         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3558         return WINED3DERR_INVALIDCALL;
3559     }
3560
3561     *ppShader =  This->stateBlock->pixelShader;
3562     if (NULL != *ppShader) {
3563         IWineD3DPixelShader_AddRef(*ppShader);
3564     }
3565     TRACE("(%p) : returning %p\n", This, *ppShader);
3566     return WINED3D_OK;
3567 }
3568
3569 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3570     IWineD3DDevice *iface,
3571     UINT start,
3572     CONST BOOL *srcData,
3573     UINT count) {
3574
3575     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3576     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3577
3578     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3579             iface, srcData, start, count);
3580
3581     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3582
3583     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3584     for (i = 0; i < cnt; i++)
3585         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3586
3587     for (i = start; i < cnt + start; ++i) {
3588         This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
3589     }
3590
3591     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3592
3593     return WINED3D_OK;
3594 }
3595
3596 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3597     IWineD3DDevice *iface,
3598     UINT start,
3599     BOOL *dstData,
3600     UINT count) {
3601
3602     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3603     int cnt = min(count, MAX_CONST_B - start);
3604
3605     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3606             iface, dstData, start, count);
3607
3608     if (dstData == NULL || cnt < 0)
3609         return WINED3DERR_INVALIDCALL;
3610
3611     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3612     return WINED3D_OK;
3613 }
3614
3615 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3616     IWineD3DDevice *iface,
3617     UINT start,
3618     CONST int *srcData,
3619     UINT count) {
3620
3621     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3622     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3623
3624     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3625             iface, srcData, start, count);
3626
3627     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3628
3629     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3630     for (i = 0; i < cnt; i++)
3631         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3632            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3633
3634     for (i = start; i < cnt + start; ++i) {
3635         This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
3636     }
3637
3638     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3639
3640     return WINED3D_OK;
3641 }
3642
3643 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3644     IWineD3DDevice *iface,
3645     UINT start,
3646     int *dstData,
3647     UINT count) {
3648
3649     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3650     int cnt = min(count, MAX_CONST_I - start);
3651
3652     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3653             iface, dstData, start, count);
3654
3655     if (dstData == NULL || cnt < 0)
3656         return WINED3DERR_INVALIDCALL;
3657
3658     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3659     return WINED3D_OK;
3660 }
3661
3662 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3663     IWineD3DDevice *iface,
3664     UINT start,
3665     CONST float *srcData,
3666     UINT count) {
3667
3668     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3669     UINT i;
3670
3671     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3672             iface, srcData, start, count);
3673
3674     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3675     if (srcData == NULL || start + count > This->d3d_pshader_constantF || start > This->d3d_pshader_constantF)
3676         return WINED3DERR_INVALIDCALL;
3677
3678     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3679     if(TRACE_ON(d3d)) {
3680         for (i = 0; i < count; i++)
3681             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3682                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3683     }
3684
3685     if (!This->isRecordingState)
3686     {
3687         This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
3688         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3689     }
3690
3691     memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
3692             sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
3693
3694     return WINED3D_OK;
3695 }
3696
3697 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3698     IWineD3DDevice *iface,
3699     UINT start,
3700     float *dstData,
3701     UINT count) {
3702
3703     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3704     int cnt = min(count, This->d3d_pshader_constantF - start);
3705
3706     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3707             iface, dstData, start, count);
3708
3709     if (dstData == NULL || cnt < 0)
3710         return WINED3DERR_INVALIDCALL;
3711
3712     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3713     return WINED3D_OK;
3714 }
3715
3716 /* Context activation is done by the caller. */
3717 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3718 static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount,
3719         const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD dwFlags,
3720         DWORD DestFVF)
3721 {
3722     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3723     unsigned int i;
3724     WINED3DVIEWPORT vp;
3725     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3726     BOOL doClip;
3727     DWORD numTextures;
3728
3729     if (stream_info->use_map & (1 << WINED3D_FFP_NORMAL))
3730     {
3731         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3732     }
3733
3734     if (!(stream_info->use_map & (1 << WINED3D_FFP_POSITION)))
3735     {
3736         ERR("Source has no position mask\n");
3737         return WINED3DERR_INVALIDCALL;
3738     }
3739
3740     /* We might access VBOs from this code, so hold the lock */
3741     ENTER_GL();
3742
3743     if (dest->resource.allocatedMemory == NULL) {
3744         buffer_get_sysmem(dest);
3745     }
3746
3747     /* Get a pointer into the destination vbo(create one if none exists) and
3748      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3749      */
3750     if (!dest->buffer_object && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT))
3751     {
3752         dest->flags |= WINED3D_BUFFER_CREATEBO;
3753         IWineD3DBuffer_PreLoad((IWineD3DBuffer *)dest);
3754     }
3755
3756     if (dest->buffer_object)
3757     {
3758         unsigned char extrabytes = 0;
3759         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3760          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3761          * this may write 4 extra bytes beyond the area that should be written
3762          */
3763         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
3764         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
3765         if(!dest_conv_addr) {
3766             ERR("Out of memory\n");
3767             /* Continue without storing converted vertices */
3768         }
3769         dest_conv = dest_conv_addr;
3770     }
3771
3772     /* Should I clip?
3773      * a) WINED3DRS_CLIPPING is enabled
3774      * b) WINED3DVOP_CLIP is passed
3775      */
3776     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3777         static BOOL warned = FALSE;
3778         /*
3779          * The clipping code is not quite correct. Some things need
3780          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3781          * so disable clipping for now.
3782          * (The graphics in Half-Life are broken, and my processvertices
3783          *  test crashes with IDirect3DDevice3)
3784         doClip = TRUE;
3785          */
3786         doClip = FALSE;
3787         if(!warned) {
3788            warned = TRUE;
3789            FIXME("Clipping is broken and disabled for now\n");
3790         }
3791     } else doClip = FALSE;
3792     dest_ptr = ((char *) buffer_get_sysmem(dest)) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3793
3794     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3795                                  WINED3DTS_VIEW,
3796                                  &view_mat);
3797     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3798                                  WINED3DTS_PROJECTION,
3799                                  &proj_mat);
3800     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3801                                  WINED3DTS_WORLDMATRIX(0),
3802                                  &world_mat);
3803
3804     TRACE("View mat:\n");
3805     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);
3806     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);
3807     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);
3808     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);
3809
3810     TRACE("Proj mat:\n");
3811     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);
3812     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);
3813     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);
3814     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);
3815
3816     TRACE("World mat:\n");
3817     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);
3818     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);
3819     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);
3820     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);
3821
3822     /* Get the viewport */
3823     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3824     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3825           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3826
3827     multiply_matrix(&mat,&view_mat,&world_mat);
3828     multiply_matrix(&mat,&proj_mat,&mat);
3829
3830     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3831
3832     for (i = 0; i < dwCount; i+= 1) {
3833         unsigned int tex_index;
3834
3835         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3836              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3837             /* The position first */
3838             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
3839             const float *p = (const float *)(element->data + i * element->stride);
3840             float x, y, z, rhw;
3841             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3842
3843             /* Multiplication with world, view and projection matrix */
3844             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);
3845             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);
3846             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);
3847             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);
3848
3849             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3850
3851             /* WARNING: The following things are taken from d3d7 and were not yet checked
3852              * against d3d8 or d3d9!
3853              */
3854
3855             /* Clipping conditions: From msdn
3856              *
3857              * A vertex is clipped if it does not match the following requirements
3858              * -rhw < x <= rhw
3859              * -rhw < y <= rhw
3860              *    0 < z <= rhw
3861              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3862              *
3863              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3864              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3865              *
3866              */
3867
3868             if( !doClip ||
3869                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3870                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3871                   ( rhw > eps ) ) ) {
3872
3873                 /* "Normal" viewport transformation (not clipped)
3874                  * 1) The values are divided by rhw
3875                  * 2) The y axis is negative, so multiply it with -1
3876                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3877                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3878                  * 4) Multiply x with Width/2 and add Width/2
3879                  * 5) The same for the height
3880                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3881                  *    The minimum Z value to z
3882                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3883                  *
3884                  * Well, basically it's simply a linear transformation into viewport
3885                  * coordinates
3886                  */
3887
3888                 x /= rhw;
3889                 y /= rhw;
3890                 z /= rhw;
3891
3892                 y *= -1;
3893
3894                 x *= vp.Width / 2;
3895                 y *= vp.Height / 2;
3896                 z *= vp.MaxZ - vp.MinZ;
3897
3898                 x += vp.Width / 2 + vp.X;
3899                 y += vp.Height / 2 + vp.Y;
3900                 z += vp.MinZ;
3901
3902                 rhw = 1 / rhw;
3903             } else {
3904                 /* That vertex got clipped
3905                  * Contrary to OpenGL it is not dropped completely, it just
3906                  * undergoes a different calculation.
3907                  */
3908                 TRACE("Vertex got clipped\n");
3909                 x += rhw;
3910                 y += rhw;
3911
3912                 x  /= 2;
3913                 y  /= 2;
3914
3915                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3916                  * outside of the main vertex buffer memory. That needs some more
3917                  * investigation...
3918                  */
3919             }
3920
3921             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3922
3923
3924             ( (float *) dest_ptr)[0] = x;
3925             ( (float *) dest_ptr)[1] = y;
3926             ( (float *) dest_ptr)[2] = z;
3927             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3928
3929             dest_ptr += 3 * sizeof(float);
3930
3931             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3932                 dest_ptr += sizeof(float);
3933             }
3934
3935             if(dest_conv) {
3936                 float w = 1 / rhw;
3937                 ( (float *) dest_conv)[0] = x * w;
3938                 ( (float *) dest_conv)[1] = y * w;
3939                 ( (float *) dest_conv)[2] = z * w;
3940                 ( (float *) dest_conv)[3] = w;
3941
3942                 dest_conv += 3 * sizeof(float);
3943
3944                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3945                     dest_conv += sizeof(float);
3946                 }
3947             }
3948         }
3949         if (DestFVF & WINED3DFVF_PSIZE) {
3950             dest_ptr += sizeof(DWORD);
3951             if(dest_conv) dest_conv += sizeof(DWORD);
3952         }
3953         if (DestFVF & WINED3DFVF_NORMAL) {
3954             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
3955             const float *normal = (const float *)(element->data + i * element->stride);
3956             /* AFAIK this should go into the lighting information */
3957             FIXME("Didn't expect the destination to have a normal\n");
3958             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3959             if(dest_conv) {
3960                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3961             }
3962         }
3963
3964         if (DestFVF & WINED3DFVF_DIFFUSE) {
3965             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
3966             const DWORD *color_d = (const DWORD *)(element->data + i * element->stride);
3967             if (!(stream_info->use_map & (1 << WINED3D_FFP_DIFFUSE)))
3968             {
3969                 static BOOL warned = FALSE;
3970
3971                 if(!warned) {
3972                     ERR("No diffuse color in source, but destination has one\n");
3973                     warned = TRUE;
3974                 }
3975
3976                 *( (DWORD *) dest_ptr) = 0xffffffff;
3977                 dest_ptr += sizeof(DWORD);
3978
3979                 if(dest_conv) {
3980                     *( (DWORD *) dest_conv) = 0xffffffff;
3981                     dest_conv += sizeof(DWORD);
3982                 }
3983             }
3984             else {
3985                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3986                 if(dest_conv) {
3987                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3988                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3989                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3990                     dest_conv += sizeof(DWORD);
3991                 }
3992             }
3993         }
3994
3995         if (DestFVF & WINED3DFVF_SPECULAR)
3996         {
3997             /* What's the color value in the feedback buffer? */
3998             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
3999             const DWORD *color_s = (const DWORD *)(element->data + i * element->stride);
4000             if (!(stream_info->use_map & (1 << WINED3D_FFP_SPECULAR)))
4001             {
4002                 static BOOL warned = FALSE;
4003
4004                 if(!warned) {
4005                     ERR("No specular color in source, but destination has one\n");
4006                     warned = TRUE;
4007                 }
4008
4009                 *( (DWORD *) dest_ptr) = 0xFF000000;
4010                 dest_ptr += sizeof(DWORD);
4011
4012                 if(dest_conv) {
4013                     *( (DWORD *) dest_conv) = 0xFF000000;
4014                     dest_conv += sizeof(DWORD);
4015                 }
4016             }
4017             else {
4018                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4019                 if(dest_conv) {
4020                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4021                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4022                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4023                     dest_conv += sizeof(DWORD);
4024                 }
4025             }
4026         }
4027
4028         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4029             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
4030             const float *tex_coord = (const float *)(element->data + i * element->stride);
4031             if (!(stream_info->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + tex_index))))
4032             {
4033                 ERR("No source texture, but destination requests one\n");
4034                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4035                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4036             }
4037             else {
4038                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4039                 if(dest_conv) {
4040                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4041                 }
4042             }
4043         }
4044     }
4045
4046     if(dest_conv) {
4047         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->buffer_object));
4048         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4049         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
4050                                       dwCount * get_flexible_vertex_size(DestFVF),
4051                                       dest_conv_addr));
4052         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4053         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
4054     }
4055
4056     LEAVE_GL();
4057
4058     return WINED3D_OK;
4059 }
4060 #undef copy_and_next
4061
4062 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex,
4063         UINT VertexCount, IWineD3DBuffer *pDestBuffer, IWineD3DVertexDeclaration *pVertexDecl, DWORD Flags,
4064         DWORD DestFVF)
4065 {
4066     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4067     struct wined3d_stream_info stream_info;
4068     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
4069     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4070
4071     if(pVertexDecl) {
4072         ERR("Output vertex declaration not implemented yet\n");
4073     }
4074
4075     /* Need any context to write to the vbo. */
4076     ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
4077
4078     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4079      * control the streamIsUP flag, thus restore it afterwards.
4080      */
4081     This->stateBlock->streamIsUP = FALSE;
4082     device_stream_info_from_declaration(This, FALSE, &stream_info, &vbo);
4083     This->stateBlock->streamIsUP = streamWasUP;
4084
4085     if(vbo || SrcStartIndex) {
4086         unsigned int i;
4087         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4088          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4089          *
4090          * Also get the start index in, but only loop over all elements if there's something to add at all.
4091          */
4092         for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
4093         {
4094             struct wined3d_stream_info_element *e;
4095
4096             if (!(stream_info.use_map & (1 << i))) continue;
4097
4098             e = &stream_info.elements[i];
4099             if (e->buffer_object)
4100             {
4101                 struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx];
4102                 e->buffer_object = 0;
4103                 e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb));
4104                 ENTER_GL();
4105                 GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
4106                 vb->buffer_object = 0;
4107                 LEAVE_GL();
4108             }
4109             if (e->data) e->data += e->stride * SrcStartIndex;
4110         }
4111     }
4112
4113     return process_vertices_strided(This, DestIndex, VertexCount, &stream_info,
4114             (struct wined3d_buffer *)pDestBuffer, Flags, DestFVF);
4115 }
4116
4117 /*****
4118  * Get / Set Texture Stage States
4119  * TODO: Verify against dx9 definitions
4120  *****/
4121 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4122     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4123     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4124
4125     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4126
4127     if (Stage >= MAX_TEXTURES) {
4128         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
4129         return WINED3D_OK;
4130     }
4131
4132     This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
4133     This->updateStateBlock->textureState[Stage][Type]         = Value;
4134
4135     if (This->isRecordingState) {
4136         TRACE("Recording... not performing anything\n");
4137         return WINED3D_OK;
4138     }
4139
4140     /* Checked after the assignments to allow proper stateblock recording */
4141     if(oldValue == Value) {
4142         TRACE("App is setting the old value over, nothing to do\n");
4143         return WINED3D_OK;
4144     }
4145
4146     if(Stage > This->stateBlock->lowest_disabled_stage &&
4147        This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4148         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4149          * Changes in other states are important on disabled stages too
4150          */
4151         return WINED3D_OK;
4152     }
4153
4154     if(Type == WINED3DTSS_COLOROP) {
4155         unsigned int i;
4156
4157         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4158             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4159              * they have to be disabled
4160              *
4161              * The current stage is dirtified below.
4162              */
4163             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4164                 TRACE("Additionally dirtifying stage %u\n", i);
4165                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4166             }
4167             This->stateBlock->lowest_disabled_stage = Stage;
4168             TRACE("New lowest disabled: %u\n", Stage);
4169         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4170             /* Previously disabled stage enabled. Stages above it may need enabling
4171              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4172              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4173              *
4174              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4175              */
4176
4177             for (i = Stage + 1; i < This->adapter->gl_info.max_texture_stages; ++i)
4178             {
4179                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4180                     break;
4181                 }
4182                 TRACE("Additionally dirtifying stage %u due to enable\n", i);
4183                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4184             }
4185             This->stateBlock->lowest_disabled_stage = i;
4186             TRACE("New lowest disabled: %u\n", i);
4187         }
4188     }
4189
4190     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4191
4192     return WINED3D_OK;
4193 }
4194
4195 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4196     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4197     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4198     *pValue = This->updateStateBlock->textureState[Stage][Type];
4199     return WINED3D_OK;
4200 }
4201
4202 /*****
4203  * Get / Set Texture
4204  *****/
4205 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface,
4206         DWORD stage, IWineD3DBaseTexture *texture)
4207 {
4208     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4209     IWineD3DBaseTexture *prev;
4210
4211     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4212
4213     if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3)
4214         stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4215
4216     /* Windows accepts overflowing this array... we do not. */
4217     if (stage >= sizeof(This->stateBlock->textures) / sizeof(*This->stateBlock->textures))
4218     {
4219         WARN("Ignoring invalid stage %u.\n", stage);
4220         return WINED3D_OK;
4221     }
4222
4223     /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4224     if (texture && ((IWineD3DTextureImpl *)texture)->resource.pool == WINED3DPOOL_SCRATCH)
4225     {
4226         WARN("Rejecting attempt to set scratch texture.\n");
4227         return WINED3DERR_INVALIDCALL;
4228     }
4229
4230     This->updateStateBlock->changed.textures |= 1 << stage;
4231
4232     prev = This->updateStateBlock->textures[stage];
4233     TRACE("Previous texture %p.\n", prev);
4234
4235     if (texture == prev)
4236     {
4237         TRACE("App is setting the same texture again, nothing to do.\n");
4238         return WINED3D_OK;
4239     }
4240
4241     TRACE("Setting new texture to %p.\n", texture);
4242     This->updateStateBlock->textures[stage] = texture;
4243
4244     if (This->isRecordingState)
4245     {
4246         TRACE("Recording... not performing anything\n");
4247
4248         if (texture) IWineD3DBaseTexture_AddRef(texture);
4249         if (prev) IWineD3DBaseTexture_Release(prev);
4250
4251         return WINED3D_OK;
4252     }
4253
4254     if (texture)
4255     {
4256         IWineD3DBaseTextureImpl *t = (IWineD3DBaseTextureImpl *)texture;
4257         LONG bind_count = InterlockedIncrement(&t->baseTexture.bindCount);
4258         UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
4259
4260         IWineD3DBaseTexture_AddRef(texture);
4261
4262         if (!prev || dimensions != IWineD3DBaseTexture_GetTextureDimensions(prev))
4263         {
4264             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
4265         }
4266
4267         if (!prev && stage < MAX_TEXTURES)
4268         {
4269             /* The source arguments for color and alpha ops have different
4270              * meanings when a NULL texture is bound, so the COLOROP and
4271              * ALPHAOP have to be dirtified. */
4272             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_COLOROP));
4273             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_ALPHAOP));
4274         }
4275
4276         if (bind_count == 1) t->baseTexture.sampler = stage;
4277     }
4278
4279     if (prev)
4280     {
4281         IWineD3DBaseTextureImpl *t = (IWineD3DBaseTextureImpl *)prev;
4282         LONG bind_count = InterlockedDecrement(&t->baseTexture.bindCount);
4283
4284         IWineD3DBaseTexture_Release(prev);
4285
4286         if (!texture && stage < MAX_TEXTURES)
4287         {
4288             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_COLOROP));
4289             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_ALPHAOP));
4290         }
4291
4292         if (bind_count && t->baseTexture.sampler == stage)
4293         {
4294             unsigned int i;
4295
4296             /* Search for other stages the texture is bound to. Shouldn't
4297              * happen if applications bind textures to a single stage only. */
4298             TRACE("Searching for other stages the texture is bound to.\n");
4299             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
4300             {
4301                 if (This->updateStateBlock->textures[i] == prev)
4302                 {
4303                     TRACE("Texture is also bound to stage %u.\n", i);
4304                     t->baseTexture.sampler = i;
4305                     break;
4306                 }
4307             }
4308         }
4309     }
4310
4311     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(stage));
4312
4313     return WINED3D_OK;
4314 }
4315
4316 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4317     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4318
4319     TRACE("(%p) : Stage %#x, ppTexture %p\n", This, Stage, ppTexture);
4320
4321     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4322         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4323     }
4324
4325     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4326         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4327         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4328     }
4329
4330     *ppTexture=This->stateBlock->textures[Stage];
4331     if (*ppTexture)
4332         IWineD3DBaseTexture_AddRef(*ppTexture);
4333
4334     TRACE("(%p) : Returning %p\n", This, *ppTexture);
4335
4336     return WINED3D_OK;
4337 }
4338
4339 /*****
4340  * Get Back Buffer
4341  *****/
4342 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4343                                                 IWineD3DSurface **ppBackBuffer) {
4344     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4345     IWineD3DSwapChain *swapChain;
4346     HRESULT hr;
4347
4348     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4349
4350     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4351     if (hr == WINED3D_OK) {
4352         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4353             IWineD3DSwapChain_Release(swapChain);
4354     } else {
4355         *ppBackBuffer = NULL;
4356     }
4357     return hr;
4358 }
4359
4360 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4361     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4362     WARN("(%p) : stub, calling idirect3d for now\n", This);
4363     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4364 }
4365
4366 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4367     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4368     IWineD3DSwapChain *swapChain;
4369     HRESULT hr;
4370
4371     if(iSwapChain > 0) {
4372         hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4373         if (hr == WINED3D_OK) {
4374             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4375             IWineD3DSwapChain_Release(swapChain);
4376         } else {
4377             FIXME("(%p) Error getting display mode\n", This);
4378         }
4379     } else {
4380         /* Don't read the real display mode,
4381            but return the stored mode instead. X11 can't change the color
4382            depth, and some apps are pretty angry if they SetDisplayMode from
4383            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4384
4385            Also don't relay to the swapchain because with ddraw it's possible
4386            that there isn't a swapchain at all */
4387         pMode->Width = This->ddraw_width;
4388         pMode->Height = This->ddraw_height;
4389         pMode->Format = This->ddraw_format;
4390         pMode->RefreshRate = 0;
4391         hr = WINED3D_OK;
4392     }
4393
4394     return hr;
4395 }
4396
4397 /*****
4398  * Stateblock related functions
4399  *****/
4400
4401 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4402     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4403     IWineD3DStateBlock *stateblock;
4404     HRESULT hr;
4405
4406     TRACE("(%p)\n", This);
4407
4408     if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
4409
4410     hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock, NULL);
4411     if (FAILED(hr)) return hr;
4412
4413     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4414     This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
4415     This->isRecordingState = TRUE;
4416
4417     TRACE("(%p) recording stateblock %p\n", This, stateblock);
4418
4419     return WINED3D_OK;
4420 }
4421
4422 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4423     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4424     IWineD3DStateBlockImpl *object = This->updateStateBlock;
4425
4426     if (!This->isRecordingState) {
4427         WARN("(%p) not recording! returning error\n", This);
4428         *ppStateBlock = NULL;
4429         return WINED3DERR_INVALIDCALL;
4430     }
4431
4432     stateblock_init_contained_states(object);
4433
4434     *ppStateBlock = (IWineD3DStateBlock*) object;
4435     This->isRecordingState = FALSE;
4436     This->updateStateBlock = This->stateBlock;
4437     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4438     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4439     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4440     return WINED3D_OK;
4441 }
4442
4443 /*****
4444  * Scene related functions
4445  *****/
4446 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4447     /* At the moment we have no need for any functionality at the beginning
4448        of a scene                                                          */
4449     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4450     TRACE("(%p)\n", This);
4451
4452     if(This->inScene) {
4453         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4454         return WINED3DERR_INVALIDCALL;
4455     }
4456     This->inScene = TRUE;
4457     return WINED3D_OK;
4458 }
4459
4460 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4461     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4462     TRACE("(%p)\n", This);
4463
4464     if(!This->inScene) {
4465         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4466         return WINED3DERR_INVALIDCALL;
4467     }
4468
4469     ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
4470     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4471     wglFlush();
4472     /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4473      * fails
4474      */
4475
4476     This->inScene = FALSE;
4477     return WINED3D_OK;
4478 }
4479
4480 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4481                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4482                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4483     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4484     IWineD3DSwapChain *swapChain = NULL;
4485     int i;
4486     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4487
4488     TRACE("(%p) Presenting the frame\n", This);
4489
4490     for(i = 0 ; i < swapchains ; i ++) {
4491
4492         IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain);
4493         TRACE("presentinng chain %d, %p\n", i, swapChain);
4494         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4495         IWineD3DSwapChain_Release(swapChain);
4496     }
4497
4498     return WINED3D_OK;
4499 }
4500
4501 /* Not called from the VTable (internal subroutine) */
4502 HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfaceImpl *target, DWORD Count,
4503                                         CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
4504                                         float Z, DWORD Stencil) {
4505     GLbitfield     glMask = 0;
4506     unsigned int   i;
4507     WINED3DRECT curRect;
4508     RECT vp_rect;
4509     const WINED3DVIEWPORT *vp = &This->stateBlock->viewport;
4510     UINT drawable_width, drawable_height;
4511     IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget;
4512     IWineD3DSwapChainImpl *swapchain = NULL;
4513     struct wined3d_context *context;
4514
4515     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4516      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4517      * for the cleared parts, and the untouched parts.
4518      *
4519      * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4520      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4521      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4522      * checking all this if the dest surface is in the drawable anyway.
4523      */
4524     if((Flags & WINED3DCLEAR_TARGET) && !(target->Flags & SFLAG_INDRAWABLE)) {
4525         while(1) {
4526             if(vp->X != 0 || vp->Y != 0 ||
4527                vp->Width < target->currentDesc.Width || vp->Height < target->currentDesc.Height) {
4528                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4529                 break;
4530             }
4531             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4532                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4533                This->stateBlock->scissorRect.right < target->currentDesc.Width ||
4534                This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) {
4535                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4536                 break;
4537             }
4538             if(Count > 0 && pRects && (
4539                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4540                pRects[0].x2 < target->currentDesc.Width ||
4541                pRects[0].y2 < target->currentDesc.Height)) {
4542                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4543                 break;
4544             }
4545             break;
4546         }
4547     }
4548
4549     context = ActivateContext(This, (IWineD3DSurface *)target, CTXUSAGE_CLEAR);
4550
4551     target->get_drawable_size(context, &drawable_width, &drawable_height);
4552
4553     ENTER_GL();
4554
4555     /* Only set the values up once, as they are not changing */
4556     if (Flags & WINED3DCLEAR_STENCIL) {
4557         glClearStencil(Stencil);
4558         checkGLcall("glClearStencil");
4559         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4560         glStencilMask(0xFFFFFFFF);
4561     }
4562
4563     if (Flags & WINED3DCLEAR_ZBUFFER) {
4564         DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
4565         glDepthMask(GL_TRUE);
4566         glClearDepth(Z);
4567         checkGLcall("glClearDepth");
4568         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4569         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4570
4571         if (vp->X != 0 || vp->Y != 0 ||
4572                 vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) {
4573             surface_load_ds_location(This->stencilBufferTarget, context, location);
4574         }
4575         else if (This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4576                 This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4577                 This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width ||
4578                 This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) {
4579             surface_load_ds_location(This->stencilBufferTarget, context, location);
4580         }
4581         else if (Count > 0 && pRects && (
4582                 pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4583                 pRects[0].x2 < depth_stencil->currentDesc.Width ||
4584                 pRects[0].y2 < depth_stencil->currentDesc.Height)) {
4585             surface_load_ds_location(This->stencilBufferTarget, context, location);
4586         }
4587     }
4588
4589     if (Flags & WINED3DCLEAR_TARGET) {
4590         TRACE("Clearing screen with glClear to color %x\n", Color);
4591         glClearColor(D3DCOLOR_R(Color),
4592                      D3DCOLOR_G(Color),
4593                      D3DCOLOR_B(Color),
4594                      D3DCOLOR_A(Color));
4595         checkGLcall("glClearColor");
4596
4597         /* Clear ALL colors! */
4598         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4599         glMask = glMask | GL_COLOR_BUFFER_BIT;
4600     }
4601
4602     vp_rect.left = vp->X;
4603     vp_rect.top = vp->Y;
4604     vp_rect.right = vp->X + vp->Width;
4605     vp_rect.bottom = vp->Y + vp->Height;
4606     if (!(Count > 0 && pRects)) {
4607         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4608             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
4609         }
4610         if (context->render_offscreen)
4611         {
4612             glScissor(vp_rect.left, vp_rect.top,
4613                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4614         } else {
4615             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
4616                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4617         }
4618         checkGLcall("glScissor");
4619         glClear(glMask);
4620         checkGLcall("glClear");
4621     } else {
4622         /* Now process each rect in turn */
4623         for (i = 0; i < Count; i++) {
4624             /* Note gl uses lower left, width/height */
4625             IntersectRect((RECT *)&curRect, &vp_rect, (const RECT *)&pRects[i]);
4626             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4627                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
4628             }
4629             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
4630                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
4631                   curRect.x1, (target->currentDesc.Height - curRect.y2),
4632                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4633
4634             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4635              * The rectangle is not cleared, no error is returned, but further rectanlges are
4636              * still cleared if they are valid
4637              */
4638             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
4639                 TRACE("Rectangle with negative dimensions, ignoring\n");
4640                 continue;
4641             }
4642
4643             if (context->render_offscreen)
4644             {
4645                 glScissor(curRect.x1, curRect.y1,
4646                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4647             } else {
4648                 glScissor(curRect.x1, drawable_height - curRect.y2,
4649                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4650             }
4651             checkGLcall("glScissor");
4652
4653             glClear(glMask);
4654             checkGLcall("glClear");
4655         }
4656     }
4657
4658     /* Restore the old values (why..?) */
4659     if (Flags & WINED3DCLEAR_STENCIL) {
4660         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4661     }
4662     if (Flags & WINED3DCLEAR_TARGET) {
4663         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4664         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4665                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4666                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4667                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4668
4669         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
4670          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
4671          */
4672         IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE);
4673     }
4674     if (Flags & WINED3DCLEAR_ZBUFFER) {
4675         /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
4676         DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
4677         surface_modify_ds_location(This->stencilBufferTarget, location);
4678     }
4679
4680     LEAVE_GL();
4681
4682     if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)target, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
4683         if (target == (IWineD3DSurfaceImpl*) swapchain->frontBuffer) {
4684             wglFlush();
4685         }
4686         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
4687     }
4688
4689     return WINED3D_OK;
4690 }
4691
4692 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4693                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4695     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
4696
4697     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
4698           Count, pRects, Flags, Color, Z, Stencil);
4699
4700     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4701         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4702         /* TODO: What about depth stencil buffers without stencil bits? */
4703         return WINED3DERR_INVALIDCALL;
4704     }
4705
4706     return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil);
4707 }
4708
4709 /*****
4710  * Drawing functions
4711  *****/
4712
4713 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
4714         WINED3DPRIMITIVETYPE primitive_type)
4715 {
4716     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4717
4718     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
4719
4720     This->updateStateBlock->changed.primitive_type = TRUE;
4721     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
4722 }
4723
4724 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
4725         WINED3DPRIMITIVETYPE *primitive_type)
4726 {
4727     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4728
4729     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
4730
4731     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
4732
4733     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
4734 }
4735
4736 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
4737 {
4738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4739
4740     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
4741
4742     if(!This->stateBlock->vertexDecl) {
4743         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4744         return WINED3DERR_INVALIDCALL;
4745     }
4746
4747     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4748     if(This->stateBlock->streamIsUP) {
4749         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4750         This->stateBlock->streamIsUP = FALSE;
4751     }
4752
4753     if(This->stateBlock->loadBaseVertexIndex != 0) {
4754         This->stateBlock->loadBaseVertexIndex = 0;
4755         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4756     }
4757     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4758     drawPrimitive(iface, vertex_count, StartVertex /* start_idx */, 0 /* indxSize */, NULL /* indxData */);
4759     return WINED3D_OK;
4760 }
4761
4762 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, UINT startIndex, UINT index_count)
4763 {
4764     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4765     UINT                 idxStride = 2;
4766     IWineD3DBuffer *pIB;
4767     GLuint vbo;
4768
4769     pIB = This->stateBlock->pIndexData;
4770     if (!pIB) {
4771         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4772          * without an index buffer set. (The first time at least...)
4773          * D3D8 simply dies, but I doubt it can do much harm to return
4774          * D3DERR_INVALIDCALL there as well. */
4775         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4776         return WINED3DERR_INVALIDCALL;
4777     }
4778
4779     if(!This->stateBlock->vertexDecl) {
4780         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4781         return WINED3DERR_INVALIDCALL;
4782     }
4783
4784     if(This->stateBlock->streamIsUP) {
4785         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4786         This->stateBlock->streamIsUP = FALSE;
4787     }
4788     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
4789
4790     TRACE("(%p) : startIndex %u, index count %u.\n", This, startIndex, index_count);
4791
4792     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
4793         idxStride = 2;
4794     } else {
4795         idxStride = 4;
4796     }
4797
4798     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4799         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4800         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4801     }
4802
4803     drawPrimitive(iface, index_count, startIndex, idxStride,
4804             vbo ? NULL : ((struct wined3d_buffer *)pIB)->resource.allocatedMemory);
4805
4806     return WINED3D_OK;
4807 }
4808
4809 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
4810         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4811 {
4812     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4813     IWineD3DBuffer *vb;
4814
4815     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4816             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
4817
4818     if(!This->stateBlock->vertexDecl) {
4819         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4820         return WINED3DERR_INVALIDCALL;
4821     }
4822
4823     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4824     vb = This->stateBlock->streamSource[0];
4825     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4826     if (vb) IWineD3DBuffer_Release(vb);
4827     This->stateBlock->streamOffset[0] = 0;
4828     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4829     This->stateBlock->streamIsUP = TRUE;
4830     This->stateBlock->loadBaseVertexIndex = 0;
4831
4832     /* TODO: Only mark dirty if drawing from a different UP address */
4833     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4834
4835     drawPrimitive(iface, vertex_count, 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */);
4836
4837     /* MSDN specifies stream zero settings must be set to NULL */
4838     This->stateBlock->streamStride[0] = 0;
4839     This->stateBlock->streamSource[0] = NULL;
4840
4841     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4842      * the new stream sources or use UP drawing again
4843      */
4844     return WINED3D_OK;
4845 }
4846
4847 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
4848         UINT index_count, const void *pIndexData, WINED3DFORMAT IndexDataFormat,
4849         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4850 {
4851     int                 idxStride;
4852     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4853     IWineD3DBuffer *vb;
4854     IWineD3DBuffer *ib;
4855
4856     TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4857             This, index_count, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4858
4859     if(!This->stateBlock->vertexDecl) {
4860         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4861         return WINED3DERR_INVALIDCALL;
4862     }
4863
4864     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
4865         idxStride = 2;
4866     } else {
4867         idxStride = 4;
4868     }
4869
4870     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4871     vb = This->stateBlock->streamSource[0];
4872     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4873     if (vb) IWineD3DBuffer_Release(vb);
4874     This->stateBlock->streamIsUP = TRUE;
4875     This->stateBlock->streamOffset[0] = 0;
4876     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4877
4878     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4879     This->stateBlock->baseVertexIndex = 0;
4880     This->stateBlock->loadBaseVertexIndex = 0;
4881     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4882     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4883     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4884
4885     drawPrimitive(iface, index_count, 0 /* start_idx */, idxStride, pIndexData);
4886
4887     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4888     This->stateBlock->streamSource[0] = NULL;
4889     This->stateBlock->streamStride[0] = 0;
4890     ib = This->stateBlock->pIndexData;
4891     if(ib) {
4892         IWineD3DBuffer_Release(ib);
4893         This->stateBlock->pIndexData = NULL;
4894     }
4895     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4896      * SetStreamSource to specify a vertex buffer
4897      */
4898
4899     return WINED3D_OK;
4900 }
4901
4902 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
4903         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
4904 {
4905     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4906
4907     /* Mark the state dirty until we have nicer tracking
4908      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4909      * that value.
4910      */
4911     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4912     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4913     This->stateBlock->baseVertexIndex = 0;
4914     This->up_strided = DrawPrimStrideData;
4915     drawPrimitive(iface, vertex_count, 0, 0, NULL);
4916     This->up_strided = NULL;
4917     return WINED3D_OK;
4918 }
4919
4920 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
4921         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
4922         UINT NumVertices, const void *pIndexData, WINED3DFORMAT IndexDataFormat)
4923 {
4924     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4925     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
4926
4927     /* Mark the state dirty until we have nicer tracking
4928      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4929      * that value.
4930      */
4931     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4932     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4933     This->stateBlock->streamIsUP = TRUE;
4934     This->stateBlock->baseVertexIndex = 0;
4935     This->up_strided = DrawPrimStrideData;
4936     drawPrimitive(iface, 0 /* numindices */, 0 /* start_idx */, idxSize, pIndexData);
4937     This->up_strided = NULL;
4938     return WINED3D_OK;
4939 }
4940
4941 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
4942     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
4943      * not callable by the app directly no parameter validation checks are needed here.
4944      */
4945     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4946     WINED3DLOCKED_BOX src;
4947     WINED3DLOCKED_BOX dst;
4948     HRESULT hr;
4949     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
4950
4951     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
4952      * dirtification to improve loading performance.
4953      */
4954     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
4955     if(FAILED(hr)) return hr;
4956     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
4957     if(FAILED(hr)) {
4958     IWineD3DVolume_UnlockBox(pSourceVolume);
4959             return hr;
4960     }
4961
4962     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
4963
4964     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
4965     if(FAILED(hr)) {
4966         IWineD3DVolume_UnlockBox(pSourceVolume);
4967     } else {
4968         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
4969     }
4970     return hr;
4971 }
4972
4973 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice *iface,
4974         IWineD3DBaseTexture *src_texture, IWineD3DBaseTexture *dst_texture)
4975 {
4976     unsigned int level_count, i;
4977     WINED3DRESOURCETYPE type;
4978     HRESULT hr;
4979
4980     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
4981
4982     /* Verify that the source and destination textures are non-NULL. */
4983     if (!src_texture || !dst_texture)
4984     {
4985         WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
4986         return WINED3DERR_INVALIDCALL;
4987     }
4988
4989     if (src_texture == dst_texture)
4990     {
4991         WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
4992         return WINED3DERR_INVALIDCALL;
4993     }
4994
4995     /* Verify that the source and destination textures are the same type. */
4996     type = IWineD3DBaseTexture_GetType(src_texture);
4997     if (IWineD3DBaseTexture_GetType(dst_texture) != type)
4998     {
4999         WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
5000         return WINED3DERR_INVALIDCALL;
5001     }
5002
5003     /* Check that both textures have the identical numbers of levels. */
5004     level_count = IWineD3DBaseTexture_GetLevelCount(src_texture);
5005     if (IWineD3DBaseTexture_GetLevelCount(dst_texture) != level_count)
5006     {
5007         WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
5008         return WINED3DERR_INVALIDCALL;
5009     }
5010
5011     /* Make sure that the destination texture is loaded. */
5012     ((IWineD3DBaseTextureImpl *)dst_texture)->baseTexture.internal_preload(dst_texture, SRGB_RGB);
5013
5014     /* Update every surface level of the texture. */
5015     switch (type)
5016     {
5017         case WINED3DRTYPE_TEXTURE:
5018         {
5019             IWineD3DSurface *src_surface;
5020             IWineD3DSurface *dst_surface;
5021
5022             for (i = 0; i < level_count; ++i)
5023             {
5024                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)src_texture, i, &src_surface);
5025                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)dst_texture, i, &dst_surface);
5026                 hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
5027                 IWineD3DSurface_Release(dst_surface);
5028                 IWineD3DSurface_Release(src_surface);
5029                 if (FAILED(hr))
5030                 {
5031                     WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
5032                     return hr;
5033                 }
5034             }
5035             break;
5036         }
5037
5038         case WINED3DRTYPE_CUBETEXTURE:
5039         {
5040             IWineD3DSurface *src_surface;
5041             IWineD3DSurface *dst_surface;
5042             WINED3DCUBEMAP_FACES face;
5043
5044             for (i = 0; i < level_count; ++i)
5045             {
5046                 /* Update each cube face. */
5047                 for (face = WINED3DCUBEMAP_FACE_POSITIVE_X; face <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++face)
5048                 {
5049                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)src_texture,
5050                             face, i, &src_surface);
5051                     if (FAILED(hr)) ERR("Failed to get src cube surface face %u, level %u, hr %#x.\n", face, i, hr);
5052                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)dst_texture,
5053                             face, i, &dst_surface);
5054                     if (FAILED(hr)) ERR("Failed to get dst cube surface face %u, level %u, hr %#x.\n", face, i, hr);
5055                     hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
5056                     IWineD3DSurface_Release(dst_surface);
5057                     IWineD3DSurface_Release(src_surface);
5058                     if (FAILED(hr))
5059                     {
5060                         WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
5061                         return hr;
5062                     }
5063                 }
5064             }
5065             break;
5066         }
5067
5068         case WINED3DRTYPE_VOLUMETEXTURE:
5069         {
5070             IWineD3DVolume *src_volume;
5071             IWineD3DVolume *dst_volume;
5072
5073             for (i = 0; i < level_count; ++i)
5074             {
5075                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)src_texture, i, &src_volume);
5076                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)dst_texture, i, &dst_volume);
5077                 hr = IWineD3DDeviceImpl_UpdateVolume(iface, src_volume, dst_volume);
5078                 IWineD3DVolume_Release(dst_volume);
5079                 IWineD3DVolume_Release(src_volume);
5080                 if (FAILED(hr))
5081                 {
5082                     WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr);
5083                     return hr;
5084                 }
5085             }
5086             break;
5087         }
5088
5089         default:
5090             FIXME("Unsupported texture type %#x.\n", type);
5091             return WINED3DERR_INVALIDCALL;
5092     }
5093
5094     return WINED3D_OK;
5095 }
5096
5097 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5098     IWineD3DSwapChain *swapChain;
5099     HRESULT hr;
5100     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5101     if(hr == WINED3D_OK) {
5102         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5103                 IWineD3DSwapChain_Release(swapChain);
5104     }
5105     return hr;
5106 }
5107
5108 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5109     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5110     IWineD3DBaseTextureImpl *texture;
5111     DWORD i;
5112
5113     TRACE("(%p) : %p\n", This, pNumPasses);
5114
5115     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5116         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) {
5117             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5118             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5119         }
5120         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) {
5121             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5122             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5123         }
5124
5125         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5126         if (!texture || texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5127
5128         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) {
5129             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5130             return E_FAIL;
5131         }
5132         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) {
5133             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5134             return E_FAIL;
5135         }
5136         if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE &&
5137            This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) {
5138             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5139             return E_FAIL;
5140         }
5141     }
5142
5143     /* return a sensible default */
5144     *pNumPasses = 1;
5145
5146     TRACE("returning D3D_OK\n");
5147     return WINED3D_OK;
5148 }
5149
5150 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5151 {
5152     int i;
5153
5154     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
5155     {
5156         IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5157         if (texture && (texture->resource.format_desc->format == WINED3DFMT_P8_UINT
5158                 || texture->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM))
5159         {
5160             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5161         }
5162     }
5163 }
5164
5165 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5166     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5167     int j;
5168     UINT NewSize;
5169     PALETTEENTRY **palettes;
5170
5171     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5172
5173     if (PaletteNumber >= MAX_PALETTES) {
5174         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5175         return WINED3DERR_INVALIDCALL;
5176     }
5177
5178     if (PaletteNumber >= This->NumberOfPalettes) {
5179         NewSize = This->NumberOfPalettes;
5180         do {
5181            NewSize *= 2;
5182         } while(PaletteNumber >= NewSize);
5183         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5184         if (!palettes) {
5185             ERR("Out of memory!\n");
5186             return E_OUTOFMEMORY;
5187         }
5188         This->palettes = palettes;
5189         This->NumberOfPalettes = NewSize;
5190     }
5191
5192     if (!This->palettes[PaletteNumber]) {
5193         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5194         if (!This->palettes[PaletteNumber]) {
5195             ERR("Out of memory!\n");
5196             return E_OUTOFMEMORY;
5197         }
5198     }
5199
5200     for (j = 0; j < 256; ++j) {
5201         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5202         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5203         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5204         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5205     }
5206     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5207     TRACE("(%p) : returning\n", This);
5208     return WINED3D_OK;
5209 }
5210
5211 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5212     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5213     int j;
5214     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5215     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5216         /* What happens in such situation isn't documented; Native seems to silently abort
5217            on such conditions. Return Invalid Call. */
5218         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5219         return WINED3DERR_INVALIDCALL;
5220     }
5221     for (j = 0; j < 256; ++j) {
5222         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5223         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5224         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5225         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5226     }
5227     TRACE("(%p) : returning\n", This);
5228     return WINED3D_OK;
5229 }
5230
5231 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5232     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5233     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5234     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5235        (tested with reference rasterizer). Return Invalid Call. */
5236     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5237         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5238         return WINED3DERR_INVALIDCALL;
5239     }
5240     /*TODO: stateblocks */
5241     if (This->currentPalette != PaletteNumber) {
5242         This->currentPalette = PaletteNumber;
5243         dirtify_p8_texture_samplers(This);
5244     }
5245     TRACE("(%p) : returning\n", This);
5246     return WINED3D_OK;
5247 }
5248
5249 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5250     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5251     if (PaletteNumber == NULL) {
5252         WARN("(%p) : returning Invalid Call\n", This);
5253         return WINED3DERR_INVALIDCALL;
5254     }
5255     /*TODO: stateblocks */
5256     *PaletteNumber = This->currentPalette;
5257     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5258     return WINED3D_OK;
5259 }
5260
5261 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5262     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5263     static BOOL warned;
5264     if (!warned)
5265     {
5266         FIXME("(%p) : stub\n", This);
5267         warned = TRUE;
5268     }
5269
5270     This->softwareVertexProcessing = bSoftware;
5271     return WINED3D_OK;
5272 }
5273
5274
5275 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5276     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5277     static BOOL warned;
5278     if (!warned)
5279     {
5280         FIXME("(%p) : stub\n", This);
5281         warned = TRUE;
5282     }
5283     return This->softwareVertexProcessing;
5284 }
5285
5286
5287 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5288     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5289     IWineD3DSwapChain *swapChain;
5290     HRESULT hr;
5291
5292     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5293
5294     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5295     if(hr == WINED3D_OK){
5296         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5297         IWineD3DSwapChain_Release(swapChain);
5298     }else{
5299         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5300     }
5301     return hr;
5302 }
5303
5304
5305 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5306     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5307     static BOOL warned;
5308     if(nSegments != 0.0f) {
5309         if (!warned)
5310         {
5311             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5312             warned = TRUE;
5313         }
5314     }
5315     return WINED3D_OK;
5316 }
5317
5318 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5319     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5320     static BOOL warned;
5321     if (!warned)
5322     {
5323         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5324         warned = TRUE;
5325     }
5326     return 0.0f;
5327 }
5328
5329 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5330     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5331     /** TODO: remove casts to IWineD3DSurfaceImpl
5332      *       NOTE: move code to surface to accomplish this
5333       ****************************************/
5334     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5335     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)pDestinationSurface;
5336     int srcWidth, srcHeight;
5337     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5338     WINED3DFORMAT destFormat, srcFormat;
5339     UINT          destSize;
5340     int srcLeft, destLeft, destTop;
5341     WINED3DPOOL       srcPool, destPool;
5342     int offset    = 0;
5343     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5344     const struct GlPixelFormatDesc *src_format_desc, *dst_format_desc;
5345     GLenum dummy;
5346     DWORD sampler;
5347     int bpp;
5348     CONVERT_TYPES convert = NO_CONVERSION;
5349
5350     WINED3DSURFACE_DESC  winedesc;
5351
5352     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5353
5354     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5355     srcSurfaceWidth = winedesc.width;
5356     srcSurfaceHeight = winedesc.height;
5357     srcPool = winedesc.pool;
5358     srcFormat = winedesc.format;
5359
5360     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5361     destSurfaceWidth = winedesc.width;
5362     destSurfaceHeight = winedesc.height;
5363     destPool = winedesc.pool;
5364     destFormat = winedesc.format;
5365     destSize = winedesc.size;
5366
5367     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5368         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5369         return WINED3DERR_INVALIDCALL;
5370     }
5371
5372     /* This call loads the opengl surface directly, instead of copying the surface to the
5373      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5374      * copy in sysmem and use regular surface loading.
5375      */
5376     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5377     if(convert != NO_CONVERSION) {
5378         return IWineD3DSurface_BltFast(pDestinationSurface,
5379                                         pDestPoint  ? pDestPoint->x : 0,
5380                                         pDestPoint  ? pDestPoint->y : 0,
5381                                         pSourceSurface, pSourceRect, 0);
5382     }
5383
5384     if (destFormat == WINED3DFMT_UNKNOWN) {
5385         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5386         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5387
5388         /* Get the update surface description */
5389         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5390     }
5391
5392     ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
5393
5394     ENTER_GL();
5395     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5396     checkGLcall("glActiveTextureARB");
5397     LEAVE_GL();
5398
5399     /* Make sure the surface is loaded and up to date */
5400     surface_internal_preload(pDestinationSurface, SRGB_RGB);
5401     IWineD3DSurface_BindTexture(pDestinationSurface, FALSE);
5402
5403     src_format_desc = ((IWineD3DSurfaceImpl *)pSrcSurface)->resource.format_desc;
5404     dst_format_desc = dst_impl->resource.format_desc;
5405
5406     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5407     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5408     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5409     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5410     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5411     destTop    = pDestPoint  ? pDestPoint->y : 0;
5412
5413
5414     /* This function doesn't support compressed textures
5415     the pitch is just bytesPerPixel * width */
5416     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5417         rowoffset = srcSurfaceWidth * src_format_desc->byte_count;
5418         offset   += srcLeft * src_format_desc->byte_count;
5419         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5420     }
5421     /* TODO DXT formats */
5422
5423     if(pSourceRect != NULL && pSourceRect->top != 0){
5424        offset +=  pSourceRect->top * srcSurfaceWidth * src_format_desc->byte_count;
5425     }
5426     TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n",
5427             This, dst_impl->texture_level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat,
5428             dst_format_desc->glType, IWineD3DSurface_GetData(pSourceSurface), offset);
5429
5430     /* Sanity check */
5431     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5432
5433         /* need to lock the surface to get the data */
5434         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5435     }
5436
5437     ENTER_GL();
5438
5439     /* TODO: Cube and volume support */
5440     if(rowoffset != 0){
5441         /* not a whole row so we have to do it a line at a time */
5442         int j;
5443
5444         /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5445         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5446
5447         for (j = destTop; j < (srcHeight + destTop); ++j)
5448         {
5449             glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, j,
5450                     srcWidth, 1, dst_format_desc->glFormat, dst_format_desc->glType,data);
5451             data += rowoffset;
5452         }
5453
5454     } else { /* Full width, so just write out the whole texture */
5455         const unsigned char* data = ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5456
5457         if (dst_format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
5458         {
5459             if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth)
5460             {
5461                 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */
5462                 FIXME("Updating part of a compressed texture is not supported.\n");
5463             }
5464             if (destFormat != srcFormat)
5465             {
5466                 FIXME("Updating mixed format compressed textures is not supported.\n");
5467             }
5468             else
5469             {
5470                 GL_EXTCALL(glCompressedTexImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5471                         dst_format_desc->glInternal, srcWidth, srcHeight, 0, destSize, data));
5472             }
5473         }
5474         else
5475         {
5476             glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, destTop,
5477                     srcWidth, srcHeight, dst_format_desc->glFormat, dst_format_desc->glType, data);
5478         }
5479      }
5480     checkGLcall("glTexSubImage2D");
5481
5482     LEAVE_GL();
5483
5484     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5485     sampler = This->rev_tex_unit_map[0];
5486     if (sampler != WINED3D_UNMAPPED_STAGE)
5487     {
5488         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5489     }
5490
5491     return WINED3D_OK;
5492 }
5493
5494 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5495     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5496     struct WineD3DRectPatch *patch;
5497     GLenum old_primitive_type;
5498     unsigned int i;
5499     struct list *e;
5500     BOOL found;
5501     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5502
5503     if(!(Handle || pRectPatchInfo)) {
5504         /* TODO: Write a test for the return value, thus the FIXME */
5505         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5506         return WINED3DERR_INVALIDCALL;
5507     }
5508
5509     if(Handle) {
5510         i = PATCHMAP_HASHFUNC(Handle);
5511         found = FALSE;
5512         LIST_FOR_EACH(e, &This->patches[i]) {
5513             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5514             if(patch->Handle == Handle) {
5515                 found = TRUE;
5516                 break;
5517             }
5518         }
5519
5520         if(!found) {
5521             TRACE("Patch does not exist. Creating a new one\n");
5522             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5523             patch->Handle = Handle;
5524             list_add_head(&This->patches[i], &patch->entry);
5525         } else {
5526             TRACE("Found existing patch %p\n", patch);
5527         }
5528     } else {
5529         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5530          * attributes we have to tesselate, read back, and draw. This needs a patch
5531          * management structure instance. Create one.
5532          *
5533          * A possible improvement is to check if a vertex shader is used, and if not directly
5534          * draw the patch.
5535          */
5536         FIXME("Drawing an uncached patch. This is slow\n");
5537         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5538     }
5539
5540     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5541        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5542        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5543         HRESULT hr;
5544         TRACE("Tesselation density or patch info changed, retesselating\n");
5545
5546         if(pRectPatchInfo) {
5547             patch->RectPatchInfo = *pRectPatchInfo;
5548         }
5549         patch->numSegs[0] = pNumSegs[0];
5550         patch->numSegs[1] = pNumSegs[1];
5551         patch->numSegs[2] = pNumSegs[2];
5552         patch->numSegs[3] = pNumSegs[3];
5553
5554         hr = tesselate_rectpatch(This, patch);
5555         if(FAILED(hr)) {
5556             WARN("Patch tesselation failed\n");
5557
5558             /* Do not release the handle to store the params of the patch */
5559             if(!Handle) {
5560                 HeapFree(GetProcessHeap(), 0, patch);
5561             }
5562             return hr;
5563         }
5564     }
5565
5566     This->currentPatch = patch;
5567     old_primitive_type = This->stateBlock->gl_primitive_type;
5568     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5569     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5570     This->stateBlock->gl_primitive_type = old_primitive_type;
5571     This->currentPatch = NULL;
5572
5573     /* Destroy uncached patches */
5574     if(!Handle) {
5575         HeapFree(GetProcessHeap(), 0, patch->mem);
5576         HeapFree(GetProcessHeap(), 0, patch);
5577     }
5578     return WINED3D_OK;
5579 }
5580
5581 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5582     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5583     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5584     FIXME("(%p) : Stub\n", This);
5585     return WINED3D_OK;
5586 }
5587
5588 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5589     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5590     int i;
5591     struct WineD3DRectPatch *patch;
5592     struct list *e;
5593     TRACE("(%p) Handle(%d)\n", This, Handle);
5594
5595     i = PATCHMAP_HASHFUNC(Handle);
5596     LIST_FOR_EACH(e, &This->patches[i]) {
5597         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5598         if(patch->Handle == Handle) {
5599             TRACE("Deleting patch %p\n", patch);
5600             list_remove(&patch->entry);
5601             HeapFree(GetProcessHeap(), 0, patch->mem);
5602             HeapFree(GetProcessHeap(), 0, patch);
5603             return WINED3D_OK;
5604         }
5605     }
5606
5607     /* TODO: Write a test for the return value */
5608     FIXME("Attempt to destroy nonexistent patch\n");
5609     return WINED3DERR_INVALIDCALL;
5610 }
5611
5612 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
5613     HRESULT hr;
5614     IWineD3DSwapChain *swapchain;
5615
5616     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
5617     if (SUCCEEDED(hr)) {
5618         IWineD3DSwapChain_Release((IUnknown *)swapchain);
5619         return swapchain;
5620     }
5621
5622     return NULL;
5623 }
5624
5625 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface,
5626         const WINED3DRECT *rect, const float color[4])
5627 {
5628     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5629     struct wined3d_context *context;
5630     IWineD3DSwapChain *swapchain;
5631
5632     swapchain = get_swapchain(surface);
5633     if (swapchain) {
5634         GLenum buffer;
5635
5636         TRACE("Surface %p is onscreen\n", surface);
5637
5638         context = ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD);
5639         ENTER_GL();
5640         context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
5641         buffer = surface_get_gl_buffer(surface, swapchain);
5642         glDrawBuffer(buffer);
5643         checkGLcall("glDrawBuffer()");
5644     } else {
5645         TRACE("Surface %p is offscreen\n", surface);
5646
5647         context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
5648         ENTER_GL();
5649         context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo);
5650         context_attach_surface_fbo(context, GL_FRAMEBUFFER, 0, surface);
5651         context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, NULL, FALSE);
5652     }
5653
5654     if (rect) {
5655         glEnable(GL_SCISSOR_TEST);
5656         if(!swapchain) {
5657             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
5658         } else {
5659             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
5660                     rect->x2 - rect->x1, rect->y2 - rect->y1);
5661         }
5662         checkGLcall("glScissor");
5663         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
5664     } else {
5665         glDisable(GL_SCISSOR_TEST);
5666     }
5667     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5668
5669     glDisable(GL_BLEND);
5670     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE));
5671
5672     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5673     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
5674
5675     glClearColor(color[0], color[1], color[2], color[3]);
5676     glClear(GL_COLOR_BUFFER_BIT);
5677     checkGLcall("glClear");
5678
5679     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
5680             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
5681         glDrawBuffer(GL_BACK);
5682         checkGLcall("glDrawBuffer()");
5683     }
5684
5685     LEAVE_GL();
5686 }
5687
5688 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
5689     unsigned int r, g, b, a;
5690     DWORD ret;
5691
5692     if (destfmt == WINED3DFMT_B8G8R8A8_UNORM
5693             || destfmt == WINED3DFMT_B8G8R8X8_UNORM
5694             || destfmt == WINED3DFMT_B8G8R8_UNORM)
5695         return color;
5696
5697     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
5698
5699     a = (color & 0xff000000) >> 24;
5700     r = (color & 0x00ff0000) >> 16;
5701     g = (color & 0x0000ff00) >>  8;
5702     b = (color & 0x000000ff) >>  0;
5703
5704     switch(destfmt)
5705     {
5706         case WINED3DFMT_B5G6R5_UNORM:
5707             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
5708             r = (r * 32) / 256;
5709             g = (g * 64) / 256;
5710             b = (b * 32) / 256;
5711             ret  = r << 11;
5712             ret |= g << 5;
5713             ret |= b;
5714             TRACE("Returning %08x\n", ret);
5715             return ret;
5716
5717         case WINED3DFMT_B5G5R5X1_UNORM:
5718         case WINED3DFMT_B5G5R5A1_UNORM:
5719             a = (a *  2) / 256;
5720             r = (r * 32) / 256;
5721             g = (g * 32) / 256;
5722             b = (b * 32) / 256;
5723             ret  = a << 15;
5724             ret |= r << 10;
5725             ret |= g <<  5;
5726             ret |= b <<  0;
5727             TRACE("Returning %08x\n", ret);
5728             return ret;
5729
5730         case WINED3DFMT_A8_UNORM:
5731             TRACE("Returning %08x\n", a);
5732             return a;
5733
5734         case WINED3DFMT_B4G4R4X4_UNORM:
5735         case WINED3DFMT_B4G4R4A4_UNORM:
5736             a = (a * 16) / 256;
5737             r = (r * 16) / 256;
5738             g = (g * 16) / 256;
5739             b = (b * 16) / 256;
5740             ret  = a << 12;
5741             ret |= r <<  8;
5742             ret |= g <<  4;
5743             ret |= b <<  0;
5744             TRACE("Returning %08x\n", ret);
5745             return ret;
5746
5747         case WINED3DFMT_B2G3R3_UNORM:
5748             r = (r * 8) / 256;
5749             g = (g * 8) / 256;
5750             b = (b * 4) / 256;
5751             ret  = r <<  5;
5752             ret |= g <<  2;
5753             ret |= b <<  0;
5754             TRACE("Returning %08x\n", ret);
5755             return ret;
5756
5757         case WINED3DFMT_R8G8B8X8_UNORM:
5758         case WINED3DFMT_R8G8B8A8_UNORM:
5759             ret  = a << 24;
5760             ret |= b << 16;
5761             ret |= g <<  8;
5762             ret |= r <<  0;
5763             TRACE("Returning %08x\n", ret);
5764             return ret;
5765
5766         case WINED3DFMT_B10G10R10A2_UNORM:
5767             a = (a *    4) / 256;
5768             r = (r * 1024) / 256;
5769             g = (g * 1024) / 256;
5770             b = (b * 1024) / 256;
5771             ret  = a << 30;
5772             ret |= r << 20;
5773             ret |= g << 10;
5774             ret |= b <<  0;
5775             TRACE("Returning %08x\n", ret);
5776             return ret;
5777
5778         case WINED3DFMT_R10G10B10A2_UNORM:
5779             a = (a *    4) / 256;
5780             r = (r * 1024) / 256;
5781             g = (g * 1024) / 256;
5782             b = (b * 1024) / 256;
5783             ret  = a << 30;
5784             ret |= b << 20;
5785             ret |= g << 10;
5786             ret |= r <<  0;
5787             TRACE("Returning %08x\n", ret);
5788             return ret;
5789
5790         default:
5791             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
5792             return 0;
5793     }
5794 }
5795
5796 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5797     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5798     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5799     WINEDDBLTFX BltFx;
5800     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
5801
5802     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5803         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5804         return WINED3DERR_INVALIDCALL;
5805     }
5806
5807     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5808         const float c[4] = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)};
5809         color_fill_fbo(iface, pSurface, pRect, c);
5810         return WINED3D_OK;
5811     } else {
5812         /* Just forward this to the DirectDraw blitting engine */
5813         memset(&BltFx, 0, sizeof(BltFx));
5814         BltFx.dwSize = sizeof(BltFx);
5815         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format_desc->format);
5816         return IWineD3DSurface_Blt(pSurface, (const RECT *)pRect, NULL, NULL,
5817                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
5818     }
5819 }
5820
5821 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
5822         IWineD3DRendertargetView *rendertarget_view, const float color[4])
5823 {
5824     IWineD3DResource *resource;
5825     IWineD3DSurface *surface;
5826     HRESULT hr;
5827
5828     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
5829     if (FAILED(hr))
5830     {
5831         ERR("Failed to get resource, hr %#x\n", hr);
5832         return;
5833     }
5834
5835     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
5836     {
5837         FIXME("Only supported on surface resources\n");
5838         IWineD3DResource_Release(resource);
5839         return;
5840     }
5841
5842     surface = (IWineD3DSurface *)resource;
5843
5844     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
5845     {
5846         color_fill_fbo(iface, surface, NULL, color);
5847     }
5848     else
5849     {
5850         WINEDDBLTFX BltFx;
5851         WINED3DCOLOR c;
5852
5853         WARN("Converting to WINED3DCOLOR, this might give incorrect results\n");
5854
5855         c = ((DWORD)(color[2] * 255.0f));
5856         c |= ((DWORD)(color[1] * 255.0f)) << 8;
5857         c |= ((DWORD)(color[0] * 255.0f)) << 16;
5858         c |= ((DWORD)(color[3] * 255.0f)) << 24;
5859
5860         /* Just forward this to the DirectDraw blitting engine */
5861         memset(&BltFx, 0, sizeof(BltFx));
5862         BltFx.dwSize = sizeof(BltFx);
5863         BltFx.u5.dwFillColor = argb_to_fmt(c, ((IWineD3DSurfaceImpl *)surface)->resource.format_desc->format);
5864         hr = IWineD3DSurface_Blt(surface, NULL, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
5865         if (FAILED(hr))
5866         {
5867             ERR("Blt failed, hr %#x\n", hr);
5868         }
5869     }
5870
5871     IWineD3DResource_Release(resource);
5872 }
5873
5874 /* rendertarget and depth stencil functions */
5875 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5876     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5877
5878     if (RenderTargetIndex >= This->adapter->gl_info.max_buffers)
5879     {
5880         ERR("(%p) : Only %d render targets are supported.\n",
5881                 This, This->adapter->gl_info.max_buffers);
5882         return WINED3DERR_INVALIDCALL;
5883     }
5884
5885     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5886     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5887     /* Note inc ref on returned surface */
5888     if(*ppRenderTarget != NULL)
5889         IWineD3DSurface_AddRef(*ppRenderTarget);
5890     return WINED3D_OK;
5891 }
5892
5893 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5894     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5895     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5896     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5897     IWineD3DSwapChainImpl *Swapchain;
5898     HRESULT hr;
5899
5900     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5901
5902     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5903     if(hr != WINED3D_OK) {
5904         ERR("Can't get the swapchain\n");
5905         return hr;
5906     }
5907
5908     /* Make sure to release the swapchain */
5909     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5910
5911     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5912         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5913         return WINED3DERR_INVALIDCALL;
5914     }
5915     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5916         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5917         return WINED3DERR_INVALIDCALL;
5918     }
5919
5920     if(Swapchain->frontBuffer != Front) {
5921         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5922
5923         if(Swapchain->frontBuffer)
5924         {
5925             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5926             ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags &= ~SFLAG_SWAPCHAIN;
5927         }
5928         Swapchain->frontBuffer = Front;
5929
5930         if(Swapchain->frontBuffer) {
5931             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5932             ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags |= SFLAG_SWAPCHAIN;
5933         }
5934     }
5935
5936     if(Back && !Swapchain->backBuffer) {
5937         /* We need memory for the back buffer array - only one back buffer this way */
5938         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5939         if(!Swapchain->backBuffer) {
5940             ERR("Out of memory\n");
5941             return E_OUTOFMEMORY;
5942         }
5943     }
5944
5945     if(Swapchain->backBuffer[0] != Back) {
5946         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5947
5948         /* What to do about the context here in the case of multithreading? Not sure.
5949          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
5950          */
5951         WARN("No active context?\n");
5952
5953         ENTER_GL();
5954         if(!Swapchain->backBuffer[0]) {
5955             /* GL was told to draw to the front buffer at creation,
5956              * undo that
5957              */
5958             glDrawBuffer(GL_BACK);
5959             checkGLcall("glDrawBuffer(GL_BACK)");
5960             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5961             Swapchain->presentParms.BackBufferCount = 1;
5962         } else if (!Back) {
5963             /* That makes problems - disable for now */
5964             /* glDrawBuffer(GL_FRONT); */
5965             checkGLcall("glDrawBuffer(GL_FRONT)");
5966             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5967             Swapchain->presentParms.BackBufferCount = 0;
5968         }
5969         LEAVE_GL();
5970
5971         if(Swapchain->backBuffer[0])
5972         {
5973             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5974             ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags &= ~SFLAG_SWAPCHAIN;
5975         }
5976         Swapchain->backBuffer[0] = Back;
5977
5978         if(Swapchain->backBuffer[0]) {
5979             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5980             ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags |= SFLAG_SWAPCHAIN;
5981         } else {
5982             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5983             Swapchain->backBuffer = NULL;
5984         }
5985
5986     }
5987
5988     return WINED3D_OK;
5989 }
5990
5991 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5992     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5993     *ppZStencilSurface = This->stencilBufferTarget;
5994     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5995
5996     if(*ppZStencilSurface != NULL) {
5997         /* Note inc ref on returned surface */
5998         IWineD3DSurface_AddRef(*ppZStencilSurface);
5999         return WINED3D_OK;
6000     } else {
6001         return WINED3DERR_NOTFOUND;
6002     }
6003 }
6004
6005 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6006         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip)
6007 {
6008     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6009     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6010     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6011     const struct wined3d_gl_info *gl_info;
6012     struct wined3d_context *context;
6013     GLenum gl_filter;
6014     POINT offset = {0, 0};
6015
6016     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6017             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6018     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6019     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6020
6021     switch (filter) {
6022         case WINED3DTEXF_LINEAR:
6023             gl_filter = GL_LINEAR;
6024             break;
6025
6026         default:
6027             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6028         case WINED3DTEXF_NONE:
6029         case WINED3DTEXF_POINT:
6030             gl_filter = GL_NEAREST;
6031             break;
6032     }
6033
6034     /* Attach src surface to src fbo */
6035     src_swapchain = get_swapchain(src_surface);
6036     dst_swapchain = get_swapchain(dst_surface);
6037
6038     if (src_swapchain) context = ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6039     else if (dst_swapchain) context = ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6040     else context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6041
6042     gl_info = context->gl_info;
6043
6044     if (src_swapchain) {
6045         GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6046
6047         TRACE("Source surface %p is onscreen\n", src_surface);
6048         /* Make sure the drawable is up to date. In the offscreen case
6049          * attach_surface_fbo() implicitly takes care of this. */
6050         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
6051
6052         if(buffer == GL_FRONT) {
6053             RECT windowsize;
6054             UINT h;
6055             ClientToScreen(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &offset);
6056             GetClientRect(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &windowsize);
6057             h = windowsize.bottom - windowsize.top;
6058             src_rect->x1 -= offset.x; src_rect->x2 -=offset.x;
6059             src_rect->y1 =  offset.y + h - src_rect->y1;
6060             src_rect->y2 =  offset.y + h - src_rect->y2;
6061         } else {
6062             src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6063             src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6064         }
6065
6066         ENTER_GL();
6067         context_bind_fbo(context, GL_READ_FRAMEBUFFER, NULL);
6068         glReadBuffer(buffer);
6069         checkGLcall("glReadBuffer()");
6070     } else {
6071         TRACE("Source surface %p is offscreen\n", src_surface);
6072         ENTER_GL();
6073         context_bind_fbo(context, GL_READ_FRAMEBUFFER, &context->src_fbo);
6074         context_attach_surface_fbo(context, GL_READ_FRAMEBUFFER, 0, src_surface);
6075         glReadBuffer(GL_COLOR_ATTACHMENT0);
6076         checkGLcall("glReadBuffer()");
6077         context_attach_depth_stencil_fbo(context, GL_READ_FRAMEBUFFER, NULL, FALSE);
6078     }
6079     LEAVE_GL();
6080
6081     /* Attach dst surface to dst fbo */
6082     if (dst_swapchain) {
6083         GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6084
6085         TRACE("Destination surface %p is onscreen\n", dst_surface);
6086         /* Make sure the drawable is up to date. In the offscreen case
6087          * attach_surface_fbo() implicitly takes care of this. */
6088         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
6089
6090         if(buffer == GL_FRONT) {
6091             RECT windowsize;
6092             UINT h;
6093             ClientToScreen(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &offset);
6094             GetClientRect(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &windowsize);
6095             h = windowsize.bottom - windowsize.top;
6096             dst_rect->x1 -= offset.x; dst_rect->x2 -=offset.x;
6097             dst_rect->y1 =  offset.y + h - dst_rect->y1;
6098             dst_rect->y2 =  offset.y + h - dst_rect->y2;
6099         } else {
6100             /* Screen coords = window coords, surface height = window height */
6101             dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6102             dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6103         }
6104
6105         ENTER_GL();
6106         context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL);
6107         glDrawBuffer(buffer);
6108         checkGLcall("glDrawBuffer()");
6109     } else {
6110         TRACE("Destination surface %p is offscreen\n", dst_surface);
6111
6112         ENTER_GL();
6113         context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, &context->dst_fbo);
6114         context_attach_surface_fbo(context, GL_DRAW_FRAMEBUFFER, 0, dst_surface);
6115         glDrawBuffer(GL_COLOR_ATTACHMENT0);
6116         checkGLcall("glDrawBuffer()");
6117         context_attach_depth_stencil_fbo(context, GL_DRAW_FRAMEBUFFER, NULL, FALSE);
6118     }
6119     glDisable(GL_SCISSOR_TEST);
6120     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6121
6122     if (flip) {
6123         gl_info->fbo_ops.glBlitFramebuffer(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6124                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter);
6125         checkGLcall("glBlitFramebuffer()");
6126     } else {
6127         gl_info->fbo_ops.glBlitFramebuffer(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6128                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter);
6129         checkGLcall("glBlitFramebuffer()");
6130     }
6131
6132     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
6133
6134     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6135     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6136             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6137         glDrawBuffer(GL_BACK);
6138         checkGLcall("glDrawBuffer()");
6139     }
6140     LEAVE_GL();
6141 }
6142
6143 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6145     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
6146
6147     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6148
6149     if (RenderTargetIndex >= This->adapter->gl_info.max_buffers)
6150     {
6151         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6152              This, RenderTargetIndex, This->adapter->gl_info.max_buffers);
6153         return WINED3DERR_INVALIDCALL;
6154     }
6155
6156     /* MSDN says that null disables the render target
6157     but a device must always be associated with a render target
6158     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6159     */
6160     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6161         FIXME("Trying to set render target 0 to NULL\n");
6162         return WINED3DERR_INVALIDCALL;
6163     }
6164     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6165         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);
6166         return WINED3DERR_INVALIDCALL;
6167     }
6168
6169     /* If we are trying to set what we already have, don't bother */
6170     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6171         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6172         return WINED3D_OK;
6173     }
6174     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6175     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6176     This->render_targets[RenderTargetIndex] = pRenderTarget;
6177
6178     /* Render target 0 is special */
6179     if(RenderTargetIndex == 0 && dxVersion > 7) {
6180         /* Finally, reset the viewport and scissor rect as the MSDN states.
6181          * Tests show that stateblock recording is ignored, the change goes
6182          * directly into the primary stateblock.
6183          */
6184         This->stateBlock->viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6185         This->stateBlock->viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6186         This->stateBlock->viewport.X      = 0;
6187         This->stateBlock->viewport.Y      = 0;
6188         This->stateBlock->viewport.MaxZ   = 1.0f;
6189         This->stateBlock->viewport.MinZ   = 0.0f;
6190         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
6191
6192         This->stateBlock->scissorRect.top = 0;
6193         This->stateBlock->scissorRect.left = 0;
6194         This->stateBlock->scissorRect.right = This->stateBlock->viewport.Width;
6195         This->stateBlock->scissorRect.bottom = This->stateBlock->viewport.Height;
6196         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
6197     }
6198     return WINED3D_OK;
6199 }
6200
6201 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6202     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6203     HRESULT  hr = WINED3D_OK;
6204     IWineD3DSurface *tmp;
6205
6206     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6207
6208     if (pNewZStencil == This->stencilBufferTarget) {
6209         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6210     } else {
6211         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6212         * depending on the renter target implementation being used.
6213         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6214         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6215         * stencil buffer and incur an extra memory overhead
6216          ******************************************************/
6217
6218         if (This->stencilBufferTarget) {
6219             if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
6220                     || ((IWineD3DSurfaceImpl *)This->stencilBufferTarget)->Flags & SFLAG_DISCARD) {
6221                 surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_DISCARDED);
6222             } else {
6223                 struct wined3d_context *context = ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
6224                 surface_load_ds_location(This->stencilBufferTarget, context, SFLAG_DS_OFFSCREEN);
6225                 surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN);
6226             }
6227         }
6228
6229         tmp = This->stencilBufferTarget;
6230         This->stencilBufferTarget = pNewZStencil;
6231         /* should we be calling the parent or the wined3d surface? */
6232         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6233         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6234         hr = WINED3D_OK;
6235
6236         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6237             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6238             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6239             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6240             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6241         }
6242     }
6243
6244     return hr;
6245 }
6246
6247 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6248                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6249     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6250     /* TODO: the use of Impl is deprecated. */
6251     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6252     WINED3DLOCKED_RECT lockedRect;
6253
6254     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6255
6256     /* some basic validation checks */
6257     if(This->cursorTexture) {
6258         ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6259         ENTER_GL();
6260         glDeleteTextures(1, &This->cursorTexture);
6261         LEAVE_GL();
6262         This->cursorTexture = 0;
6263     }
6264
6265     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6266         This->haveHardwareCursor = TRUE;
6267     else
6268         This->haveHardwareCursor = FALSE;
6269
6270     if(pCursorBitmap) {
6271         WINED3DLOCKED_RECT rect;
6272
6273         /* MSDN: Cursor must be A8R8G8B8 */
6274         if (pSur->resource.format_desc->format != WINED3DFMT_B8G8R8A8_UNORM)
6275         {
6276             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6277             return WINED3DERR_INVALIDCALL;
6278         }
6279
6280         /* MSDN: Cursor must be smaller than the display mode */
6281         if(pSur->currentDesc.Width > This->ddraw_width ||
6282            pSur->currentDesc.Height > This->ddraw_height) {
6283             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);
6284             return WINED3DERR_INVALIDCALL;
6285         }
6286
6287         if (!This->haveHardwareCursor) {
6288             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6289
6290             /* Do not store the surface's pointer because the application may
6291              * release it after setting the cursor image. Windows doesn't
6292              * addref the set surface, so we can't do this either without
6293              * creating circular refcount dependencies. Copy out the gl texture
6294              * instead.
6295              */
6296             This->cursorWidth = pSur->currentDesc.Width;
6297             This->cursorHeight = pSur->currentDesc.Height;
6298             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6299             {
6300                 const struct GlPixelFormatDesc *glDesc =
6301                         getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, &This->adapter->gl_info);
6302                 char *mem, *bits = rect.pBits;
6303                 GLint intfmt = glDesc->glInternal;
6304                 GLint format = glDesc->glFormat;
6305                 GLint type = glDesc->glType;
6306                 INT height = This->cursorHeight;
6307                 INT width = This->cursorWidth;
6308                 INT bpp = glDesc->byte_count;
6309                 DWORD sampler;
6310                 INT i;
6311
6312                 /* Reformat the texture memory (pitch and width can be
6313                  * different) */
6314                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6315                 for(i = 0; i < height; i++)
6316                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6317                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6318
6319                 ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6320
6321                 ENTER_GL();
6322
6323                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6324                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6325                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6326                 }
6327
6328                 /* Make sure that a proper texture unit is selected */
6329                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6330                 checkGLcall("glActiveTextureARB");
6331                 sampler = This->rev_tex_unit_map[0];
6332                 if (sampler != WINED3D_UNMAPPED_STAGE)
6333                 {
6334                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
6335                 }
6336                 /* Create a new cursor texture */
6337                 glGenTextures(1, &This->cursorTexture);
6338                 checkGLcall("glGenTextures");
6339                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6340                 checkGLcall("glBindTexture");
6341                 /* Copy the bitmap memory into the cursor texture */
6342                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6343                 HeapFree(GetProcessHeap(), 0, mem);
6344                 checkGLcall("glTexImage2D");
6345
6346                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6347                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6348                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6349                 }
6350
6351                 LEAVE_GL();
6352             }
6353             else
6354             {
6355                 FIXME("A cursor texture was not returned.\n");
6356                 This->cursorTexture = 0;
6357             }
6358         }
6359         else
6360         {
6361             /* Draw a hardware cursor */
6362             ICONINFO cursorInfo;
6363             HCURSOR cursor;
6364             /* Create and clear maskBits because it is not needed for
6365              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6366              * chunks. */
6367             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6368                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6369             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6370                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6371                                          WINED3DLOCK_READONLY
6372             );
6373             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6374                   pSur->currentDesc.Height);
6375
6376             cursorInfo.fIcon = FALSE;
6377             cursorInfo.xHotspot = XHotSpot;
6378             cursorInfo.yHotspot = YHotSpot;
6379             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width, pSur->currentDesc.Height,
6380                     1, 1, maskBits);
6381             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width, pSur->currentDesc.Height,
6382                     1, 32, lockedRect.pBits);
6383             IWineD3DSurface_UnlockRect(pCursorBitmap);
6384             /* Create our cursor and clean up. */
6385             cursor = CreateIconIndirect(&cursorInfo);
6386             SetCursor(cursor);
6387             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6388             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6389             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6390             This->hardwareCursor = cursor;
6391             HeapFree(GetProcessHeap(), 0, maskBits);
6392         }
6393     }
6394
6395     This->xHotSpot = XHotSpot;
6396     This->yHotSpot = YHotSpot;
6397     return WINED3D_OK;
6398 }
6399
6400 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6402     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6403
6404     This->xScreenSpace = XScreenSpace;
6405     This->yScreenSpace = YScreenSpace;
6406
6407     return;
6408
6409 }
6410
6411 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6412     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6413     BOOL oldVisible = This->bCursorVisible;
6414     POINT pt;
6415
6416     TRACE("(%p) : visible(%d)\n", This, bShow);
6417
6418     /*
6419      * When ShowCursor is first called it should make the cursor appear at the OS's last
6420      * known cursor position.  Because of this, some applications just repetitively call
6421      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6422      */
6423     GetCursorPos(&pt);
6424     This->xScreenSpace = pt.x;
6425     This->yScreenSpace = pt.y;
6426
6427     if (This->haveHardwareCursor) {
6428         This->bCursorVisible = bShow;
6429         if (bShow)
6430             SetCursor(This->hardwareCursor);
6431         else
6432             SetCursor(NULL);
6433     }
6434     else
6435     {
6436         if (This->cursorTexture)
6437             This->bCursorVisible = bShow;
6438     }
6439
6440     return oldVisible;
6441 }
6442
6443 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6444     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6445     IWineD3DResourceImpl *resource;
6446     TRACE("(%p) : state (%u)\n", This, This->state);
6447
6448     /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
6449     switch (This->state) {
6450     case WINED3D_OK:
6451         return WINED3D_OK;
6452     case WINED3DERR_DEVICELOST:
6453         {
6454             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6455                 if (resource->resource.pool == WINED3DPOOL_DEFAULT)
6456                     return WINED3DERR_DEVICENOTRESET;
6457             }
6458             return WINED3DERR_DEVICELOST;
6459         }
6460     case WINED3DERR_DRIVERINTERNALERROR:
6461         return WINED3DERR_DRIVERINTERNALERROR;
6462     }
6463
6464     /* Unknown state */
6465     return WINED3DERR_DRIVERINTERNALERROR;
6466 }
6467
6468 static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) {
6469     TRACE("checking resource %p for eviction\n", resource);
6470     if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) {
6471         TRACE("Evicting %p\n", resource);
6472         IWineD3DResource_UnLoad(resource);
6473     }
6474     IWineD3DResource_Release(resource);
6475     return S_OK;
6476 }
6477
6478 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6479     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6480     TRACE("(%p)\n", This);
6481
6482     IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL);
6483     return WINED3D_OK;
6484 }
6485
6486 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
6487 {
6488     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
6489
6490     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6491     if(surface->Flags & SFLAG_DIBSECTION) {
6492         /* Release the DC */
6493         SelectObject(surface->hDC, surface->dib.holdbitmap);
6494         DeleteDC(surface->hDC);
6495         /* Release the DIB section */
6496         DeleteObject(surface->dib.DIBsection);
6497         surface->dib.bitmap_data = NULL;
6498         surface->resource.allocatedMemory = NULL;
6499         surface->Flags &= ~SFLAG_DIBSECTION;
6500     }
6501     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6502     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6503     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE) ||
6504         GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) {
6505         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6506         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6507     } else {
6508         surface->pow2Width = surface->pow2Height = 1;
6509         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6510         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6511     }
6512     surface->glRect.left = 0;
6513     surface->glRect.top = 0;
6514     surface->glRect.right = surface->pow2Width;
6515     surface->glRect.bottom = surface->pow2Height;
6516
6517     if (surface->texture_name)
6518     {
6519         ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6520         ENTER_GL();
6521         glDeleteTextures(1, &surface->texture_name);
6522         LEAVE_GL();
6523         surface->texture_name = 0;
6524         surface->Flags &= ~SFLAG_CLIENT;
6525     }
6526     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6527        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6528         surface->Flags |= SFLAG_NONPOW2;
6529     } else  {
6530         surface->Flags &= ~SFLAG_NONPOW2;
6531     }
6532     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
6533     surface->resource.allocatedMemory = NULL;
6534     surface->resource.heapMemory = NULL;
6535     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6536     /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
6537     if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) {
6538         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INSYSMEM, TRUE);
6539     } else {
6540         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INDRAWABLE, TRUE);
6541     }
6542 }
6543
6544 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6545     TRACE("Unloading resource %p\n", resource);
6546     IWineD3DResource_UnLoad(resource);
6547     IWineD3DResource_Release(resource);
6548     return S_OK;
6549 }
6550
6551 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
6552 {
6553     UINT i, count;
6554     WINED3DDISPLAYMODE m;
6555     HRESULT hr;
6556
6557     /* All Windowed modes are supported, as is leaving the current mode */
6558     if(pp->Windowed) return TRUE;
6559     if(!pp->BackBufferWidth) return TRUE;
6560     if(!pp->BackBufferHeight) return TRUE;
6561
6562     count = IWineD3D_GetAdapterModeCount(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN);
6563     for(i = 0; i < count; i++) {
6564         memset(&m, 0, sizeof(m));
6565         hr = IWineD3D_EnumAdapterModes(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN, i, &m);
6566         if(FAILED(hr)) {
6567             ERR("EnumAdapterModes failed\n");
6568         }
6569         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
6570             /* Mode found, it is supported */
6571             return TRUE;
6572         }
6573     }
6574     /* Mode not found -> not supported */
6575     return FALSE;
6576 }
6577
6578 void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) {
6579     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6580     IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface;
6581     const struct wined3d_context *context;
6582     const struct wined3d_gl_info *gl_info;
6583     UINT i;
6584     IWineD3DBaseShaderImpl *shader;
6585
6586     context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6587     gl_info = context->gl_info;
6588
6589     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6590     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6591         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6592     }
6593
6594     ENTER_GL();
6595     if(This->depth_blt_texture) {
6596         glDeleteTextures(1, &This->depth_blt_texture);
6597         This->depth_blt_texture = 0;
6598     }
6599     if (This->depth_blt_rb) {
6600         gl_info->fbo_ops.glDeleteRenderbuffers(1, &This->depth_blt_rb);
6601         This->depth_blt_rb = 0;
6602         This->depth_blt_rb_w = 0;
6603         This->depth_blt_rb_h = 0;
6604     }
6605     LEAVE_GL();
6606
6607     This->blitter->free_private(iface);
6608     This->frag_pipe->free_private(iface);
6609     This->shader_backend->shader_free_private(iface);
6610
6611     ENTER_GL();
6612     for (i = 0; i < This->adapter->gl_info.max_textures; ++i)
6613     {
6614         /* Textures are recreated below */
6615         glDeleteTextures(1, &This->dummyTextureName[i]);
6616         checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])");
6617         This->dummyTextureName[i] = 0;
6618     }
6619     LEAVE_GL();
6620
6621     while(This->numContexts) {
6622         DestroyContext(This, This->contexts[0]);
6623     }
6624     HeapFree(GetProcessHeap(), 0, swapchain->context);
6625     swapchain->context = NULL;
6626     swapchain->num_contexts = 0;
6627 }
6628
6629 HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) {
6630     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6631     IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface;
6632     HRESULT hr;
6633     IWineD3DSurfaceImpl *target;
6634
6635     /* Recreate the primary swapchain's context */
6636     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
6637     if(swapchain->backBuffer) {
6638         target = (IWineD3DSurfaceImpl *) swapchain->backBuffer[0];
6639     } else {
6640         target = (IWineD3DSurfaceImpl *) swapchain->frontBuffer;
6641     }
6642     swapchain->context[0] = CreateContext(This, target, swapchain->win_handle, FALSE,
6643                                           &swapchain->presentParms);
6644     swapchain->num_contexts = 1;
6645
6646     create_dummy_textures(This);
6647
6648     hr = This->shader_backend->shader_alloc_private(iface);
6649     if(FAILED(hr)) {
6650         ERR("Failed to recreate shader private data\n");
6651         goto err_out;
6652     }
6653     hr = This->frag_pipe->alloc_private(iface);
6654     if(FAILED(hr)) {
6655         TRACE("Fragment pipeline private data couldn't be allocated\n");
6656         goto err_out;
6657     }
6658     hr = This->blitter->alloc_private(iface);
6659     if(FAILED(hr)) {
6660         TRACE("Blitter private data couldn't be allocated\n");
6661         goto err_out;
6662     }
6663
6664     return WINED3D_OK;
6665
6666 err_out:
6667     This->blitter->free_private(iface);
6668     This->frag_pipe->free_private(iface);
6669     This->shader_backend->shader_free_private(iface);
6670     return hr;
6671 }
6672
6673 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6674     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6675     IWineD3DSwapChainImpl *swapchain;
6676     HRESULT hr;
6677     BOOL DisplayModeChanged = FALSE;
6678     WINED3DDISPLAYMODE mode;
6679     TRACE("(%p)\n", This);
6680
6681     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6682     if(FAILED(hr)) {
6683         ERR("Failed to get the first implicit swapchain\n");
6684         return hr;
6685     }
6686
6687     if(!is_display_mode_supported(This, pPresentationParameters)) {
6688         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6689         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
6690              pPresentationParameters->BackBufferHeight);
6691         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6692         return WINED3DERR_INVALIDCALL;
6693     }
6694
6695     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6696      * on an existing gl context, so there's no real need for recreation.
6697      *
6698      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6699      *
6700      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6701      */
6702     TRACE("New params:\n");
6703     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6704     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6705     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6706     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6707     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6708     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6709     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6710     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6711     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6712     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6713     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6714     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6715     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6716
6717     /* No special treatment of these parameters. Just store them */
6718     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6719     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6720     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6721     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6722
6723     /* What to do about these? */
6724     if(pPresentationParameters->BackBufferCount != 0 &&
6725         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6726         ERR("Cannot change the back buffer count yet\n");
6727     }
6728     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6729         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6730         ERR("Cannot change the back buffer format yet\n");
6731     }
6732     if(pPresentationParameters->hDeviceWindow != NULL &&
6733         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6734         ERR("Cannot change the device window yet\n");
6735     }
6736     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil_buffer) {
6737         HRESULT hrc;
6738
6739         TRACE("Creating the depth stencil buffer\n");
6740
6741         hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
6742                 This->parent,
6743                 pPresentationParameters->BackBufferWidth,
6744                 pPresentationParameters->BackBufferHeight,
6745                 pPresentationParameters->AutoDepthStencilFormat,
6746                 pPresentationParameters->MultiSampleType,
6747                 pPresentationParameters->MultiSampleQuality,
6748                 FALSE,
6749                 &This->auto_depth_stencil_buffer);
6750
6751         if (FAILED(hrc)) {
6752             ERR("Failed to create the depth stencil buffer\n");
6753             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6754             return WINED3DERR_INVALIDCALL;
6755         }
6756     }
6757
6758     /* Reset the depth stencil */
6759     if (pPresentationParameters->EnableAutoDepthStencil)
6760         IWineD3DDevice_SetDepthStencilSurface(iface, This->auto_depth_stencil_buffer);
6761     else
6762         IWineD3DDevice_SetDepthStencilSurface(iface, NULL);
6763
6764     TRACE("Resetting stateblock\n");
6765     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
6766     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
6767
6768     delete_opengl_contexts(iface, (IWineD3DSwapChain *) swapchain);
6769
6770     if(pPresentationParameters->Windowed) {
6771         mode.Width = swapchain->orig_width;
6772         mode.Height = swapchain->orig_height;
6773         mode.RefreshRate = 0;
6774         mode.Format = swapchain->presentParms.BackBufferFormat;
6775     } else {
6776         mode.Width = pPresentationParameters->BackBufferWidth;
6777         mode.Height = pPresentationParameters->BackBufferHeight;
6778         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6779         mode.Format = swapchain->presentParms.BackBufferFormat;
6780     }
6781
6782     /* Should Width == 800 && Height == 0 set 800x600? */
6783     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6784        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6785         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6786     {
6787         UINT i;
6788
6789         if(!pPresentationParameters->Windowed) {
6790             DisplayModeChanged = TRUE;
6791         }
6792         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6793         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6794
6795         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6796         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6797             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6798         }
6799         if(This->auto_depth_stencil_buffer) {
6800             updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters);
6801         }
6802     }
6803
6804     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6805        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
6806         DisplayModeChanged) {
6807
6808         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6809
6810         if(swapchain->win_handle && !pPresentationParameters->Windowed) {
6811             if(swapchain->presentParms.Windowed) {
6812                 /* switch from windowed to fs */
6813                 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle,
6814                                                          pPresentationParameters->BackBufferWidth,
6815                                                          pPresentationParameters->BackBufferHeight);
6816             } else {
6817                 /* Fullscreen -> fullscreen mode change */
6818                 MoveWindow(swapchain->win_handle, 0, 0,
6819                            pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
6820                            TRUE);
6821             }
6822         } else if(swapchain->win_handle && !swapchain->presentParms.Windowed) {
6823             /* Fullscreen -> windowed switch */
6824             IWineD3DDeviceImpl_RestoreWindow(iface, swapchain->win_handle);
6825         }
6826         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6827     } else if(!pPresentationParameters->Windowed) {
6828         DWORD style = This->style, exStyle = This->exStyle;
6829         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6830          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6831          * Reset to clear up their mess. Guild Wars also loses the device during that.
6832          */
6833         This->style = 0;
6834         This->exStyle = 0;
6835         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle,
6836                                                  pPresentationParameters->BackBufferWidth,
6837                                                  pPresentationParameters->BackBufferHeight);
6838         This->style = style;
6839         This->exStyle = exStyle;
6840     }
6841
6842     /* Note: No parent needed for initial internal stateblock */
6843     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock, NULL);
6844     if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6845     else TRACE("Created stateblock %p\n", This->stateBlock);
6846     This->updateStateBlock = This->stateBlock;
6847     IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
6848
6849     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
6850     if(FAILED(hr)) {
6851         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6852     }
6853
6854     hr = create_primary_opengl_context(iface, (IWineD3DSwapChain *) swapchain);
6855     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6856
6857     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6858      * first use
6859      */
6860     return hr;
6861 }
6862
6863 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6864     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6865     /** FIXME: always true at the moment **/
6866     if(!bEnableDialogs) {
6867         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6868     }
6869     return WINED3D_OK;
6870 }
6871
6872
6873 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6874     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6875     TRACE("(%p) : pParameters %p\n", This, pParameters);
6876
6877     *pParameters = This->createParms;
6878     return WINED3D_OK;
6879 }
6880
6881 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6882     IWineD3DSwapChain *swapchain;
6883
6884     TRACE("Relaying  to swapchain\n");
6885
6886     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6887         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, pRamp);
6888         IWineD3DSwapChain_Release(swapchain);
6889     }
6890     return;
6891 }
6892
6893 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6894     IWineD3DSwapChain *swapchain;
6895
6896     TRACE("Relaying  to swapchain\n");
6897
6898     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6899         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6900         IWineD3DSwapChain_Release(swapchain);
6901     }
6902     return;
6903 }
6904
6905
6906 /** ********************************************************
6907 *   Notification functions
6908 ** ********************************************************/
6909 /** This function must be called in the release of a resource when ref == 0,
6910 * the contents of resource must still be correct,
6911 * any handles to other resource held by the caller must be closed
6912 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6913  *****************************************************/
6914 void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6915 {
6916     TRACE("(%p) : Adding resource %p\n", This, resource);
6917
6918     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6919 }
6920
6921 static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6922 {
6923     TRACE("(%p) : Removing resource %p\n", This, resource);
6924
6925     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6926 }
6927
6928 void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6929 {
6930     WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource);
6931     int counter;
6932
6933     TRACE("(%p) : resource %p\n", This, resource);
6934
6935     context_resource_released((IWineD3DDevice *)This, resource, type);
6936
6937     switch (type) {
6938         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6939         case WINED3DRTYPE_SURFACE: {
6940             unsigned int i;
6941
6942             if (This->d3d_initialized)
6943             {
6944                 for (i = 0; i < This->adapter->gl_info.max_buffers; ++i)
6945                 {
6946                     if (This->render_targets[i] == (IWineD3DSurface *)resource) {
6947                         This->render_targets[i] = NULL;
6948                     }
6949                 }
6950                 if (This->stencilBufferTarget == (IWineD3DSurface *)resource) {
6951                     This->stencilBufferTarget = NULL;
6952                 }
6953             }
6954
6955             break;
6956         }
6957         case WINED3DRTYPE_TEXTURE:
6958         case WINED3DRTYPE_CUBETEXTURE:
6959         case WINED3DRTYPE_VOLUMETEXTURE:
6960                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
6961                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6962                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6963                         This->stateBlock->textures[counter] = NULL;
6964                     }
6965                     if (This->updateStateBlock != This->stateBlock ){
6966                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6967                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6968                             This->updateStateBlock->textures[counter] = NULL;
6969                         }
6970                     }
6971                 }
6972         break;
6973         case WINED3DRTYPE_VOLUME:
6974         /* TODO: nothing really? */
6975         break;
6976         case WINED3DRTYPE_BUFFER:
6977         {
6978             int streamNumber;
6979             TRACE("Cleaning up stream pointers\n");
6980
6981             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6982                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6983                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6984                 */
6985                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6986                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6987                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6988                         This->updateStateBlock->streamSource[streamNumber] = 0;
6989                         /* Set changed flag? */
6990                     }
6991                 }
6992                 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) */
6993                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6994                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6995                         This->stateBlock->streamSource[streamNumber] = 0;
6996                     }
6997                 }
6998             }
6999
7000             if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7001                 if (This->updateStateBlock->pIndexData == (IWineD3DBuffer *)resource) {
7002                     This->updateStateBlock->pIndexData =  NULL;
7003                 }
7004             }
7005             if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7006                 if (This->stateBlock->pIndexData == (IWineD3DBuffer *)resource) {
7007                     This->stateBlock->pIndexData =  NULL;
7008                 }
7009             }
7010         }
7011         break;
7012
7013         default:
7014         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7015         break;
7016     }
7017
7018
7019     /* Remove the resource from the resourceStore */
7020     device_resource_remove(This, resource);
7021
7022     TRACE("Resource released\n");
7023
7024 }
7025
7026 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
7027     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7028     IWineD3DResourceImpl *resource, *cursor;
7029     HRESULT ret;
7030     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
7031
7032     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
7033         TRACE("enumerating resource %p\n", resource);
7034         IWineD3DResource_AddRef((IWineD3DResource *) resource);
7035         ret = pCallback((IWineD3DResource *) resource, pData);
7036         if(ret == S_FALSE) {
7037             TRACE("Canceling enumeration\n");
7038             break;
7039         }
7040     }
7041     return WINED3D_OK;
7042 }
7043
7044 /**********************************************************
7045  * IWineD3DDevice VTbl follows
7046  **********************************************************/
7047
7048 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7049 {
7050     /*** IUnknown methods ***/
7051     IWineD3DDeviceImpl_QueryInterface,
7052     IWineD3DDeviceImpl_AddRef,
7053     IWineD3DDeviceImpl_Release,
7054     /*** IWineD3DDevice methods ***/
7055     IWineD3DDeviceImpl_GetParent,
7056     /*** Creation methods**/
7057     IWineD3DDeviceImpl_CreateBuffer,
7058     IWineD3DDeviceImpl_CreateVertexBuffer,
7059     IWineD3DDeviceImpl_CreateIndexBuffer,
7060     IWineD3DDeviceImpl_CreateStateBlock,
7061     IWineD3DDeviceImpl_CreateSurface,
7062     IWineD3DDeviceImpl_CreateRendertargetView,
7063     IWineD3DDeviceImpl_CreateTexture,
7064     IWineD3DDeviceImpl_CreateVolumeTexture,
7065     IWineD3DDeviceImpl_CreateVolume,
7066     IWineD3DDeviceImpl_CreateCubeTexture,
7067     IWineD3DDeviceImpl_CreateQuery,
7068     IWineD3DDeviceImpl_CreateSwapChain,
7069     IWineD3DDeviceImpl_CreateVertexDeclaration,
7070     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7071     IWineD3DDeviceImpl_CreateVertexShader,
7072     IWineD3DDeviceImpl_CreatePixelShader,
7073     IWineD3DDeviceImpl_CreatePalette,
7074     /*** Odd functions **/
7075     IWineD3DDeviceImpl_Init3D,
7076     IWineD3DDeviceImpl_InitGDI,
7077     IWineD3DDeviceImpl_Uninit3D,
7078     IWineD3DDeviceImpl_UninitGDI,
7079     IWineD3DDeviceImpl_SetMultithreaded,
7080     IWineD3DDeviceImpl_EvictManagedResources,
7081     IWineD3DDeviceImpl_GetAvailableTextureMem,
7082     IWineD3DDeviceImpl_GetBackBuffer,
7083     IWineD3DDeviceImpl_GetCreationParameters,
7084     IWineD3DDeviceImpl_GetDeviceCaps,
7085     IWineD3DDeviceImpl_GetDirect3D,
7086     IWineD3DDeviceImpl_GetDisplayMode,
7087     IWineD3DDeviceImpl_SetDisplayMode,
7088     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7089     IWineD3DDeviceImpl_GetRasterStatus,
7090     IWineD3DDeviceImpl_GetSwapChain,
7091     IWineD3DDeviceImpl_Reset,
7092     IWineD3DDeviceImpl_SetDialogBoxMode,
7093     IWineD3DDeviceImpl_SetCursorProperties,
7094     IWineD3DDeviceImpl_SetCursorPosition,
7095     IWineD3DDeviceImpl_ShowCursor,
7096     IWineD3DDeviceImpl_TestCooperativeLevel,
7097     /*** Getters and setters **/
7098     IWineD3DDeviceImpl_SetClipPlane,
7099     IWineD3DDeviceImpl_GetClipPlane,
7100     IWineD3DDeviceImpl_SetClipStatus,
7101     IWineD3DDeviceImpl_GetClipStatus,
7102     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7103     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7104     IWineD3DDeviceImpl_SetDepthStencilSurface,
7105     IWineD3DDeviceImpl_GetDepthStencilSurface,
7106     IWineD3DDeviceImpl_SetGammaRamp,
7107     IWineD3DDeviceImpl_GetGammaRamp,
7108     IWineD3DDeviceImpl_SetIndexBuffer,
7109     IWineD3DDeviceImpl_GetIndexBuffer,
7110     IWineD3DDeviceImpl_SetBaseVertexIndex,
7111     IWineD3DDeviceImpl_GetBaseVertexIndex,
7112     IWineD3DDeviceImpl_SetLight,
7113     IWineD3DDeviceImpl_GetLight,
7114     IWineD3DDeviceImpl_SetLightEnable,
7115     IWineD3DDeviceImpl_GetLightEnable,
7116     IWineD3DDeviceImpl_SetMaterial,
7117     IWineD3DDeviceImpl_GetMaterial,
7118     IWineD3DDeviceImpl_SetNPatchMode,
7119     IWineD3DDeviceImpl_GetNPatchMode,
7120     IWineD3DDeviceImpl_SetPaletteEntries,
7121     IWineD3DDeviceImpl_GetPaletteEntries,
7122     IWineD3DDeviceImpl_SetPixelShader,
7123     IWineD3DDeviceImpl_GetPixelShader,
7124     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7125     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7126     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7127     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7128     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7129     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7130     IWineD3DDeviceImpl_SetRenderState,
7131     IWineD3DDeviceImpl_GetRenderState,
7132     IWineD3DDeviceImpl_SetRenderTarget,
7133     IWineD3DDeviceImpl_GetRenderTarget,
7134     IWineD3DDeviceImpl_SetFrontBackBuffers,
7135     IWineD3DDeviceImpl_SetSamplerState,
7136     IWineD3DDeviceImpl_GetSamplerState,
7137     IWineD3DDeviceImpl_SetScissorRect,
7138     IWineD3DDeviceImpl_GetScissorRect,
7139     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7140     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7141     IWineD3DDeviceImpl_SetStreamSource,
7142     IWineD3DDeviceImpl_GetStreamSource,
7143     IWineD3DDeviceImpl_SetStreamSourceFreq,
7144     IWineD3DDeviceImpl_GetStreamSourceFreq,
7145     IWineD3DDeviceImpl_SetTexture,
7146     IWineD3DDeviceImpl_GetTexture,
7147     IWineD3DDeviceImpl_SetTextureStageState,
7148     IWineD3DDeviceImpl_GetTextureStageState,
7149     IWineD3DDeviceImpl_SetTransform,
7150     IWineD3DDeviceImpl_GetTransform,
7151     IWineD3DDeviceImpl_SetVertexDeclaration,
7152     IWineD3DDeviceImpl_GetVertexDeclaration,
7153     IWineD3DDeviceImpl_SetVertexShader,
7154     IWineD3DDeviceImpl_GetVertexShader,
7155     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7156     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7157     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7158     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7159     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7160     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7161     IWineD3DDeviceImpl_SetViewport,
7162     IWineD3DDeviceImpl_GetViewport,
7163     IWineD3DDeviceImpl_MultiplyTransform,
7164     IWineD3DDeviceImpl_ValidateDevice,
7165     IWineD3DDeviceImpl_ProcessVertices,
7166     /*** State block ***/
7167     IWineD3DDeviceImpl_BeginStateBlock,
7168     IWineD3DDeviceImpl_EndStateBlock,
7169     /*** Scene management ***/
7170     IWineD3DDeviceImpl_BeginScene,
7171     IWineD3DDeviceImpl_EndScene,
7172     IWineD3DDeviceImpl_Present,
7173     IWineD3DDeviceImpl_Clear,
7174     IWineD3DDeviceImpl_ClearRendertargetView,
7175     /*** Drawing ***/
7176     IWineD3DDeviceImpl_SetPrimitiveType,
7177     IWineD3DDeviceImpl_GetPrimitiveType,
7178     IWineD3DDeviceImpl_DrawPrimitive,
7179     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7180     IWineD3DDeviceImpl_DrawPrimitiveUP,
7181     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7182     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7183     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7184     IWineD3DDeviceImpl_DrawRectPatch,
7185     IWineD3DDeviceImpl_DrawTriPatch,
7186     IWineD3DDeviceImpl_DeletePatch,
7187     IWineD3DDeviceImpl_ColorFill,
7188     IWineD3DDeviceImpl_UpdateTexture,
7189     IWineD3DDeviceImpl_UpdateSurface,
7190     IWineD3DDeviceImpl_GetFrontBufferData,
7191     /*** object tracking ***/
7192     IWineD3DDeviceImpl_EnumResources
7193 };
7194
7195 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7196     DWORD rep = This->StateTable[state].representative;
7197     struct wined3d_context *context;
7198     DWORD idx;
7199     BYTE shift;
7200     UINT i;
7201
7202     for(i = 0; i < This->numContexts; i++) {
7203         context = This->contexts[i];
7204         if(isStateDirty(context, rep)) continue;
7205
7206         context->dirtyArray[context->numDirtyEntries++] = rep;
7207         idx = rep >> 5;
7208         shift = rep & 0x1f;
7209         context->isStateDirty[idx] |= (1 << shift);
7210     }
7211 }
7212
7213 void get_drawable_size_pbuffer(struct wined3d_context *context, UINT *width, UINT *height)
7214 {
7215     IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->current_rt)->resource.wineD3DDevice;
7216     /* The drawable size of a pbuffer render target is the current pbuffer size. */
7217     *width = device->pbufferWidth;
7218     *height = device->pbufferHeight;
7219 }
7220
7221 void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height)
7222 {
7223     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->current_rt;
7224     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
7225     *width = surface->pow2Width;
7226     *height = surface->pow2Height;
7227 }
7228
7229 void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height)
7230 {
7231     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)context->surface;
7232     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7233      * current context's drawable, which is the size of the back buffer of the swapchain
7234      * the active context belongs to. The back buffer of the swapchain is stored as the
7235      * surface the context belongs to. */
7236     *width = surface->currentDesc.Width;
7237     *height = surface->currentDesc.Height;
7238 }