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