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