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