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