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