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