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