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