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