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