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