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