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