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