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