jscript: Added String_link implementation.
[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, This->lastActiveRenderTarget, 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, This->lastActiveRenderTarget, 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         This->lastActiveRenderTarget = swapchain->backBuffer[0];
2162     }
2163     else {
2164         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2165         This->render_targets[0] = swapchain->frontBuffer;
2166         This->lastActiveRenderTarget = swapchain->frontBuffer;
2167     }
2168     IWineD3DSurface_AddRef(This->render_targets[0]);
2169     This->activeContext = swapchain->context[0];
2170     This->lastThread = GetCurrentThreadId();
2171
2172     /* Depth Stencil support */
2173     This->stencilBufferTarget = This->auto_depth_stencil_buffer;
2174     if (NULL != This->stencilBufferTarget) {
2175         IWineD3DSurface_AddRef(This->stencilBufferTarget);
2176     }
2177
2178     hr = This->shader_backend->shader_alloc_private(iface);
2179     if(FAILED(hr)) {
2180         TRACE("Shader private data couldn't be allocated\n");
2181         goto err_out;
2182     }
2183     hr = This->frag_pipe->alloc_private(iface);
2184     if(FAILED(hr)) {
2185         TRACE("Fragment pipeline private data couldn't be allocated\n");
2186         goto err_out;
2187     }
2188     hr = This->blitter->alloc_private(iface);
2189     if(FAILED(hr)) {
2190         TRACE("Blitter private data couldn't be allocated\n");
2191         goto err_out;
2192     }
2193
2194     /* Set up some starting GL setup */
2195
2196     /* Setup all the devices defaults */
2197     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2198     create_dummy_textures(This);
2199
2200     ENTER_GL();
2201
2202     /* Initialize the current view state */
2203     This->view_ident = 1;
2204     This->contexts[0]->last_was_rhw = 0;
2205     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2206     checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
2207
2208     switch(wined3d_settings.offscreen_rendering_mode) {
2209         case ORM_FBO:
2210         case ORM_PBUFFER:
2211             This->offscreenBuffer = GL_BACK;
2212             break;
2213
2214         case ORM_BACKBUFFER:
2215         {
2216             if(This->activeContext->aux_buffers > 0) {
2217                 TRACE("Using auxilliary buffer for offscreen rendering\n");
2218                 This->offscreenBuffer = GL_AUX0;
2219             } else {
2220                 TRACE("Using back buffer for offscreen rendering\n");
2221                 This->offscreenBuffer = GL_BACK;
2222             }
2223         }
2224     }
2225
2226     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2227     LEAVE_GL();
2228
2229     /* Clear the screen */
2230     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
2231                           WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
2232                           0x00, 1.0f, 0);
2233
2234     This->d3d_initialized = TRUE;
2235
2236     if(wined3d_settings.logo) {
2237         IWineD3DDeviceImpl_LoadLogo(This, wined3d_settings.logo);
2238     }
2239     This->highest_dirty_ps_const = 0;
2240     This->highest_dirty_vs_const = 0;
2241     return WINED3D_OK;
2242
2243 err_out:
2244     HeapFree(GetProcessHeap(), 0, This->render_targets);
2245     HeapFree(GetProcessHeap(), 0, This->draw_buffers);
2246     HeapFree(GetProcessHeap(), 0, This->swapchains);
2247     This->NumberOfSwapChains = 0;
2248     if(This->palettes) {
2249         HeapFree(GetProcessHeap(), 0, This->palettes[0]);
2250         HeapFree(GetProcessHeap(), 0, This->palettes);
2251     }
2252     This->NumberOfPalettes = 0;
2253     if(swapchain) {
2254         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2255     }
2256     if(This->stateBlock) {
2257         IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->stateBlock);
2258         This->stateBlock = NULL;
2259     }
2260     if (This->blit_priv) {
2261         This->blitter->free_private(iface);
2262     }
2263     if (This->fragment_priv) {
2264         This->frag_pipe->free_private(iface);
2265     }
2266     if (This->shader_priv) {
2267         This->shader_backend->shader_free_private(iface);
2268     }
2269     return hr;
2270 }
2271
2272 static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface,
2273         WINED3DPRESENT_PARAMETERS *pPresentationParameters)
2274 {
2275     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2276     IWineD3DSwapChainImpl *swapchain = NULL;
2277     HRESULT hr;
2278
2279     /* Setup the implicit swapchain */
2280     TRACE("Creating implicit swapchain\n");
2281     hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
2282             pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
2283     if (FAILED(hr))
2284     {
2285         WARN("Failed to create implicit swapchain\n");
2286         goto err_out;
2287     }
2288
2289     This->NumberOfSwapChains = 1;
2290     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2291     if(!This->swapchains) {
2292         ERR("Out of memory!\n");
2293         goto err_out;
2294     }
2295     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2296     return WINED3D_OK;
2297
2298 err_out:
2299     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2300     return hr;
2301 }
2302
2303 static HRESULT WINAPI device_unload_resource(IWineD3DResource *resource, void *ctx)
2304 {
2305     IWineD3DResource_UnLoad(resource);
2306     IWineD3DResource_Release(resource);
2307     return WINED3D_OK;
2308 }
2309
2310 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
2311     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2312     int sampler;
2313     UINT i;
2314     TRACE("(%p)\n", This);
2315
2316     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2317
2318     /* I don't think that the interface guarantees that the device is destroyed from the same thread
2319      * it was created. Thus make sure a context is active for the glDelete* calls
2320      */
2321     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
2322
2323     if(This->logo_surface) IWineD3DSurface_Release(This->logo_surface);
2324
2325     /* Unload resources */
2326     IWineD3DDevice_EnumResources(iface, device_unload_resource, NULL);
2327
2328     TRACE("Deleting high order patches\n");
2329     for(i = 0; i < PATCHMAP_SIZE; i++) {
2330         struct list *e1, *e2;
2331         struct WineD3DRectPatch *patch;
2332         LIST_FOR_EACH_SAFE(e1, e2, &This->patches[i]) {
2333             patch = LIST_ENTRY(e1, struct WineD3DRectPatch, entry);
2334             IWineD3DDevice_DeletePatch(iface, patch->Handle);
2335         }
2336     }
2337
2338     /* Delete the palette conversion shader if it is around */
2339     if(This->paletteConversionShader) {
2340         ENTER_GL();
2341         GL_EXTCALL(glDeleteProgramsARB(1, &This->paletteConversionShader));
2342         LEAVE_GL();
2343         This->paletteConversionShader = 0;
2344     }
2345
2346     /* Delete the pbuffer context if there is any */
2347     if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
2348
2349     /* Delete the mouse cursor texture */
2350     if(This->cursorTexture) {
2351         ENTER_GL();
2352         glDeleteTextures(1, &This->cursorTexture);
2353         LEAVE_GL();
2354         This->cursorTexture = 0;
2355     }
2356
2357     for (sampler = 0; sampler < MAX_FRAGMENT_SAMPLERS; ++sampler) {
2358         IWineD3DDevice_SetTexture(iface, sampler, NULL);
2359     }
2360     for (sampler = 0; sampler < MAX_VERTEX_SAMPLERS; ++sampler) {
2361         IWineD3DDevice_SetTexture(iface, WINED3DVERTEXTEXTURESAMPLER0 + sampler, NULL);
2362     }
2363
2364     /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
2365      * private data, it might contain opengl pointers
2366      */
2367     if(This->depth_blt_texture) {
2368         ENTER_GL();
2369         glDeleteTextures(1, &This->depth_blt_texture);
2370         LEAVE_GL();
2371         This->depth_blt_texture = 0;
2372     }
2373     if (This->depth_blt_rb) {
2374         ENTER_GL();
2375         GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This->depth_blt_rb));
2376         LEAVE_GL();
2377         This->depth_blt_rb = 0;
2378         This->depth_blt_rb_w = 0;
2379         This->depth_blt_rb_h = 0;
2380     }
2381
2382     /* Release the update stateblock */
2383     if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
2384         if(This->updateStateBlock != This->stateBlock)
2385             FIXME("(%p) Something's still holding the Update stateblock\n",This);
2386     }
2387     This->updateStateBlock = NULL;
2388
2389     { /* because were not doing proper internal refcounts releasing the primary state block
2390         causes recursion with the extra checks in ResourceReleased, to avoid this we have
2391         to set this->stateBlock = NULL; first */
2392         IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
2393         This->stateBlock = NULL;
2394
2395         /* Release the stateblock */
2396         if(IWineD3DStateBlock_Release(stateBlock) > 0){
2397             FIXME("(%p) Something's still holding the Update stateblock\n",This);
2398         }
2399     }
2400
2401     /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2402     This->blitter->free_private(iface);
2403     This->frag_pipe->free_private(iface);
2404     This->shader_backend->shader_free_private(iface);
2405
2406     /* Release the buffers (with sanity checks)*/
2407     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2408     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2409         if(This->auto_depth_stencil_buffer != This->stencilBufferTarget)
2410             FIXME("(%p) Something's still holding the stencilBufferTarget\n",This);
2411     }
2412     This->stencilBufferTarget = NULL;
2413
2414     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
2415     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
2416           /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2417     }
2418     TRACE("Setting rendertarget to NULL\n");
2419     This->render_targets[0] = NULL;
2420
2421     if (This->auto_depth_stencil_buffer) {
2422         if(D3DCB_DestroyDepthStencilSurface(This->auto_depth_stencil_buffer) > 0) {
2423             FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This);
2424         }
2425         This->auto_depth_stencil_buffer = NULL;
2426     }
2427
2428     for(i=0; i < This->NumberOfSwapChains; i++) {
2429         TRACE("Releasing the implicit swapchain %d\n", i);
2430         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
2431             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2432         }
2433     }
2434
2435     HeapFree(GetProcessHeap(), 0, This->swapchains);
2436     This->swapchains = NULL;
2437     This->NumberOfSwapChains = 0;
2438
2439     for (i = 0; i < This->NumberOfPalettes; i++) HeapFree(GetProcessHeap(), 0, This->palettes[i]);
2440     HeapFree(GetProcessHeap(), 0, This->palettes);
2441     This->palettes = NULL;
2442     This->NumberOfPalettes = 0;
2443
2444     HeapFree(GetProcessHeap(), 0, This->render_targets);
2445     HeapFree(GetProcessHeap(), 0, This->draw_buffers);
2446     This->render_targets = NULL;
2447     This->draw_buffers = NULL;
2448
2449     This->d3d_initialized = FALSE;
2450     return WINED3D_OK;
2451 }
2452
2453 static HRESULT WINAPI IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice *iface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
2454     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2455     unsigned int i;
2456
2457     for(i=0; i < This->NumberOfSwapChains; i++) {
2458         TRACE("Releasing the implicit swapchain %d\n", i);
2459         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
2460             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2461         }
2462     }
2463
2464     HeapFree(GetProcessHeap(), 0, This->swapchains);
2465     This->swapchains = NULL;
2466     This->NumberOfSwapChains = 0;
2467     return WINED3D_OK;
2468 }
2469
2470 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2471  * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2472  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2473  *
2474  * There is no way to deactivate thread safety once it is enabled.
2475  */
2476 static void WINAPI IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice *iface) {
2477     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2478
2479     /*For now just store the flag(needed in case of ddraw) */
2480     This->createParms.BehaviorFlags |= WINED3DCREATE_MULTITHREADED;
2481
2482     return;
2483 }
2484
2485 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain,
2486         const WINED3DDISPLAYMODE* pMode) {
2487     DEVMODEW devmode;
2488     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2489     LONG ret;
2490     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(pMode->Format, &GLINFO_LOCATION);
2491     RECT clip_rc;
2492
2493     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2494
2495     /* Resize the screen even without a window:
2496      * The app could have unset it with SetCooperativeLevel, but not called
2497      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2498      * but we don't have any hwnd
2499      */
2500
2501     memset(&devmode, 0, sizeof(devmode));
2502     devmode.dmSize = sizeof(devmode);
2503     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2504     devmode.dmBitsPerPel = format_desc->byte_count * 8;
2505     devmode.dmPelsWidth  = pMode->Width;
2506     devmode.dmPelsHeight = pMode->Height;
2507
2508     devmode.dmDisplayFrequency = pMode->RefreshRate;
2509     if (pMode->RefreshRate != 0)  {
2510         devmode.dmFields |= DM_DISPLAYFREQUENCY;
2511     }
2512
2513     /* Only change the mode if necessary */
2514     if( (This->ddraw_width == pMode->Width) &&
2515         (This->ddraw_height == pMode->Height) &&
2516         (This->ddraw_format == pMode->Format) &&
2517         (pMode->RefreshRate == 0) ) {
2518         return WINED3D_OK;
2519     }
2520
2521     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2522     if (ret != DISP_CHANGE_SUCCESSFUL) {
2523         if(devmode.dmDisplayFrequency != 0) {
2524             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2525             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2526             devmode.dmDisplayFrequency = 0;
2527             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2528         }
2529         if(ret != DISP_CHANGE_SUCCESSFUL) {
2530             return WINED3DERR_NOTAVAILABLE;
2531         }
2532     }
2533
2534     /* Store the new values */
2535     This->ddraw_width = pMode->Width;
2536     This->ddraw_height = pMode->Height;
2537     This->ddraw_format = pMode->Format;
2538
2539     /* And finally clip mouse to our screen */
2540     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2541     ClipCursor(&clip_rc);
2542
2543     return WINED3D_OK;
2544 }
2545
2546 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2547    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2548    *ppD3D= This->wineD3D;
2549    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2550    IWineD3D_AddRef(*ppD3D);
2551    return WINED3D_OK;
2552 }
2553
2554 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2555     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2556
2557     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2558          (This->adapter->TextureRam/(1024*1024)),
2559          ((This->adapter->TextureRam - This->adapter->UsedTextureRam) / (1024*1024)));
2560     /* return simulated texture memory left */
2561     return (This->adapter->TextureRam - This->adapter->UsedTextureRam);
2562 }
2563
2564 /*****
2565  * Get / Set Stream Source
2566  *****/
2567 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,
2568         IWineD3DBuffer *pStreamData, UINT OffsetInBytes, UINT Stride)
2569 {
2570     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2571     IWineD3DBuffer *oldSrc;
2572
2573     if (StreamNumber >= MAX_STREAMS) {
2574         WARN("Stream out of range %d\n", StreamNumber);
2575         return WINED3DERR_INVALIDCALL;
2576     } else if(OffsetInBytes & 0x3) {
2577         WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes);
2578         return WINED3DERR_INVALIDCALL;
2579     }
2580
2581     oldSrc = This->updateStateBlock->streamSource[StreamNumber];
2582     TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
2583
2584     This->updateStateBlock->changed.streamSource |= 1 << StreamNumber;
2585
2586     if(oldSrc == pStreamData &&
2587        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2588        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
2589        TRACE("Application is setting the old values over, nothing to do\n");
2590        return WINED3D_OK;
2591     }
2592
2593     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2594     if (pStreamData) {
2595         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
2596         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
2597     }
2598
2599     /* Handle recording of state blocks */
2600     if (This->isRecordingState) {
2601         TRACE("Recording... not performing anything\n");
2602         if (pStreamData) IWineD3DBuffer_AddRef(pStreamData);
2603         if (oldSrc) IWineD3DBuffer_Release(oldSrc);
2604         return WINED3D_OK;
2605     }
2606
2607     if (pStreamData != NULL) {
2608         InterlockedIncrement(&((struct wined3d_buffer *)pStreamData)->bind_count);
2609         IWineD3DBuffer_AddRef(pStreamData);
2610     }
2611     if (oldSrc != NULL) {
2612         InterlockedDecrement(&((struct wined3d_buffer *)oldSrc)->bind_count);
2613         IWineD3DBuffer_Release(oldSrc);
2614     }
2615
2616     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2617
2618     return WINED3D_OK;
2619 }
2620
2621 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface,
2622         UINT StreamNumber, IWineD3DBuffer **pStream, UINT *pOffset, UINT *pStride)
2623 {
2624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2625
2626     TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This, StreamNumber,
2627            This->stateBlock->streamSource[StreamNumber],
2628            This->stateBlock->streamOffset[StreamNumber],
2629            This->stateBlock->streamStride[StreamNumber]);
2630
2631     if (StreamNumber >= MAX_STREAMS) {
2632         WARN("Stream out of range %d\n", StreamNumber);
2633         return WINED3DERR_INVALIDCALL;
2634     }
2635     *pStream = This->stateBlock->streamSource[StreamNumber];
2636     *pStride = This->stateBlock->streamStride[StreamNumber];
2637     if (pOffset) {
2638         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2639     }
2640
2641     if (*pStream != NULL) {
2642         IWineD3DBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2643     }
2644     return WINED3D_OK;
2645 }
2646
2647 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2648     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2649     UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2650     UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2651
2652     /* Verify input at least in d3d9 this is invalid*/
2653     if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (Divider & WINED3DSTREAMSOURCE_INDEXEDDATA)){
2654         WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2655         return WINED3DERR_INVALIDCALL;
2656     }
2657     if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && StreamNumber == 0 ){
2658         WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2659         return WINED3DERR_INVALIDCALL;
2660     }
2661     if( Divider == 0 ){
2662         WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2663         return WINED3DERR_INVALIDCALL;
2664     }
2665
2666     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2667     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2668
2669     This->updateStateBlock->changed.streamFreq |= 1 << StreamNumber;
2670     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2671
2672     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2673        This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2674         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2675     }
2676
2677     return WINED3D_OK;
2678 }
2679
2680 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2681     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2682
2683     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2684     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2685
2686     TRACE("(%p) : returning %d\n", This, *Divider);
2687
2688     return WINED3D_OK;
2689 }
2690
2691 /*****
2692  * Get / Set & Multiply Transform
2693  *****/
2694 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2695     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2696
2697     /* Most of this routine, comments included copied from ddraw tree initially: */
2698     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2699
2700     /* Handle recording of state blocks */
2701     if (This->isRecordingState) {
2702         TRACE("Recording... not performing anything\n");
2703         This->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f);
2704         This->updateStateBlock->transforms[d3dts] = *lpmatrix;
2705         return WINED3D_OK;
2706     }
2707
2708     /*
2709      * If the new matrix is the same as the current one,
2710      * we cut off any further processing. this seems to be a reasonable
2711      * optimization because as was noticed, some apps (warcraft3 for example)
2712      * tend towards setting the same matrix repeatedly for some reason.
2713      *
2714      * From here on we assume that the new matrix is different, wherever it matters.
2715      */
2716     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2717         TRACE("The app is setting the same matrix over again\n");
2718         return WINED3D_OK;
2719     } else {
2720         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2721     }
2722
2723     /*
2724        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2725        where ViewMat = Camera space, WorldMat = world space.
2726
2727        In OpenGL, camera and world space is combined into GL_MODELVIEW
2728        matrix.  The Projection matrix stay projection matrix.
2729      */
2730
2731     /* Capture the times we can just ignore the change for now */
2732     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrix */
2733         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2734         /* Handled by the state manager */
2735     }
2736
2737     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2738     return WINED3D_OK;
2739
2740 }
2741 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2742     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2743     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2744     *pMatrix = This->stateBlock->transforms[State];
2745     return WINED3D_OK;
2746 }
2747
2748 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2749     const WINED3DMATRIX *mat = NULL;
2750     WINED3DMATRIX temp;
2751
2752     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2753      * below means it will be recorded in a state block change, but it
2754      * works regardless where it is recorded.
2755      * If this is found to be wrong, change to StateBlock.
2756      */
2757     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2758     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2759
2760     if (State <= HIGHEST_TRANSFORMSTATE)
2761     {
2762         mat = &This->updateStateBlock->transforms[State];
2763     } else {
2764         FIXME("Unhandled transform state!!\n");
2765     }
2766
2767     multiply_matrix(&temp, mat, pMatrix);
2768
2769     /* Apply change via set transform - will reapply to eg. lights this way */
2770     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2771 }
2772
2773 /*****
2774  * Get / Set Light
2775  *****/
2776 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2777    you can reference any indexes you want as long as that number max are enabled at any
2778    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2779    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2780    but when recording, just build a chain pretty much of commands to be replayed.                  */
2781
2782 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2783     float rho;
2784     PLIGHTINFOEL *object = NULL;
2785     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2786     struct list *e;
2787
2788     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2789     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2790
2791     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2792      * the gl driver.
2793      */
2794     if(!pLight) {
2795         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2796         return WINED3DERR_INVALIDCALL;
2797     }
2798
2799     switch(pLight->Type) {
2800         case WINED3DLIGHT_POINT:
2801         case WINED3DLIGHT_SPOT:
2802         case WINED3DLIGHT_PARALLELPOINT:
2803         case WINED3DLIGHT_GLSPOT:
2804             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2805              * most wanted
2806              */
2807             if (pLight->Attenuation0 < 0.0f || pLight->Attenuation1 < 0.0f || pLight->Attenuation2 < 0.0f)
2808             {
2809                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2810                 return WINED3DERR_INVALIDCALL;
2811             }
2812             break;
2813
2814         case WINED3DLIGHT_DIRECTIONAL:
2815             /* Ignores attenuation */
2816             break;
2817
2818         default:
2819         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2820         return WINED3DERR_INVALIDCALL;
2821     }
2822
2823     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2824         object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2825         if(object->OriginalIndex == Index) break;
2826         object = NULL;
2827     }
2828
2829     if(!object) {
2830         TRACE("Adding new light\n");
2831         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2832         if(!object) {
2833             ERR("Out of memory error when allocating a light\n");
2834             return E_OUTOFMEMORY;
2835         }
2836         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2837         object->glIndex = -1;
2838         object->OriginalIndex = Index;
2839         object->changed = TRUE;
2840     }
2841
2842     /* Initialize the object */
2843     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,
2844           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2845           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2846           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2847     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2848           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2849     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2850
2851     /* Save away the information */
2852     object->OriginalParms = *pLight;
2853
2854     switch (pLight->Type) {
2855     case WINED3DLIGHT_POINT:
2856         /* Position */
2857         object->lightPosn[0] = pLight->Position.x;
2858         object->lightPosn[1] = pLight->Position.y;
2859         object->lightPosn[2] = pLight->Position.z;
2860         object->lightPosn[3] = 1.0f;
2861         object->cutoff = 180.0f;
2862         /* FIXME: Range */
2863         break;
2864
2865     case WINED3DLIGHT_DIRECTIONAL:
2866         /* Direction */
2867         object->lightPosn[0] = -pLight->Direction.x;
2868         object->lightPosn[1] = -pLight->Direction.y;
2869         object->lightPosn[2] = -pLight->Direction.z;
2870         object->lightPosn[3] = 0.0f;
2871         object->exponent     = 0.0f;
2872         object->cutoff       = 180.0f;
2873         break;
2874
2875     case WINED3DLIGHT_SPOT:
2876         /* Position */
2877         object->lightPosn[0] = pLight->Position.x;
2878         object->lightPosn[1] = pLight->Position.y;
2879         object->lightPosn[2] = pLight->Position.z;
2880         object->lightPosn[3] = 1.0f;
2881
2882         /* Direction */
2883         object->lightDirn[0] = pLight->Direction.x;
2884         object->lightDirn[1] = pLight->Direction.y;
2885         object->lightDirn[2] = pLight->Direction.z;
2886         object->lightDirn[3] = 1.0f;
2887
2888         /*
2889          * opengl-ish and d3d-ish spot lights use too different models for the
2890          * light "intensity" as a function of the angle towards the main light direction,
2891          * so we only can approximate very roughly.
2892          * however spot lights are rather rarely used in games (if ever used at all).
2893          * furthermore if still used, probably nobody pays attention to such details.
2894          */
2895         if (pLight->Falloff == 0) {
2896             /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2897              * falloff resp. exponent parameter as an exponent, so the spot light lighting
2898              * will always be 1.0 for both of them, and we don't have to care for the
2899              * rest of the rather complex calculation
2900              */
2901             object->exponent = 0.0f;
2902         } else {
2903             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2904             if (rho < 0.0001f) rho = 0.0001f;
2905             object->exponent = -0.3f/logf(cosf(rho/2));
2906         }
2907         if (object->exponent > 128.0f)
2908         {
2909             object->exponent = 128.0f;
2910         }
2911         object->cutoff = pLight->Phi*90/M_PI;
2912
2913         /* FIXME: Range */
2914         break;
2915
2916     default:
2917         FIXME("Unrecognized light type %d\n", pLight->Type);
2918     }
2919
2920     /* Update the live definitions if the light is currently assigned a glIndex */
2921     if (object->glIndex != -1 && !This->isRecordingState) {
2922         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2923     }
2924     return WINED3D_OK;
2925 }
2926
2927 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2928     PLIGHTINFOEL *lightInfo = NULL;
2929     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2930     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2931     struct list *e;
2932     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2933
2934     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2935         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2936         if(lightInfo->OriginalIndex == Index) break;
2937         lightInfo = NULL;
2938     }
2939
2940     if (lightInfo == NULL) {
2941         TRACE("Light information requested but light not defined\n");
2942         return WINED3DERR_INVALIDCALL;
2943     }
2944
2945     *pLight = lightInfo->OriginalParms;
2946     return WINED3D_OK;
2947 }
2948
2949 /*****
2950  * Get / Set Light Enable
2951  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2952  *****/
2953 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2954     PLIGHTINFOEL *lightInfo = NULL;
2955     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2956     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2957     struct list *e;
2958     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2959
2960     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2961         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2962         if(lightInfo->OriginalIndex == Index) break;
2963         lightInfo = NULL;
2964     }
2965     TRACE("Found light: %p\n", lightInfo);
2966
2967     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2968     if (lightInfo == NULL) {
2969
2970         TRACE("Light enabled requested but light not defined, so defining one!\n");
2971         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2972
2973         /* Search for it again! Should be fairly quick as near head of list */
2974         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2975             lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2976             if(lightInfo->OriginalIndex == Index) break;
2977             lightInfo = NULL;
2978         }
2979         if (lightInfo == NULL) {
2980             FIXME("Adding default lights has failed dismally\n");
2981             return WINED3DERR_INVALIDCALL;
2982         }
2983     }
2984
2985     lightInfo->enabledChanged = TRUE;
2986     if(!Enable) {
2987         if(lightInfo->glIndex != -1) {
2988             if(!This->isRecordingState) {
2989                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2990             }
2991
2992             This->updateStateBlock->activeLights[lightInfo->glIndex] = NULL;
2993             lightInfo->glIndex = -1;
2994         } else {
2995             TRACE("Light already disabled, nothing to do\n");
2996         }
2997         lightInfo->enabled = FALSE;
2998     } else {
2999         lightInfo->enabled = TRUE;
3000         if (lightInfo->glIndex != -1) {
3001             /* nop */
3002             TRACE("Nothing to do as light was enabled\n");
3003         } else {
3004             int i;
3005             /* Find a free gl light */
3006             for(i = 0; i < This->maxConcurrentLights; i++) {
3007                 if(This->updateStateBlock->activeLights[i] == NULL) {
3008                     This->updateStateBlock->activeLights[i] = lightInfo;
3009                     lightInfo->glIndex = i;
3010                     break;
3011                 }
3012             }
3013             if(lightInfo->glIndex == -1) {
3014                 /* Our tests show that Windows returns D3D_OK in this situation, even with
3015                  * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
3016                  * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
3017                  * as well for those lights.
3018                  *
3019                  * TODO: Test how this affects rendering
3020                  */
3021                 WARN("Too many concurrently active lights\n");
3022                 return WINED3D_OK;
3023             }
3024
3025             /* i == lightInfo->glIndex */
3026             if(!This->isRecordingState) {
3027                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
3028             }
3029         }
3030     }
3031
3032     return WINED3D_OK;
3033 }
3034
3035 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3036
3037     PLIGHTINFOEL *lightInfo = NULL;
3038     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3039     struct list *e;
3040     UINT Hi = LIGHTMAP_HASHFUNC(Index);
3041     TRACE("(%p) : for idx(%d)\n", This, Index);
3042
3043     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
3044         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
3045         if(lightInfo->OriginalIndex == Index) break;
3046         lightInfo = NULL;
3047     }
3048
3049     if (lightInfo == NULL) {
3050         TRACE("Light enabled state requested but light not defined\n");
3051         return WINED3DERR_INVALIDCALL;
3052     }
3053     /* true is 128 according to SetLightEnable */
3054     *pEnable = lightInfo->enabled ? 128 : 0;
3055     return WINED3D_OK;
3056 }
3057
3058 /*****
3059  * Get / Set Clip Planes
3060  *****/
3061 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3062     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3063     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3064
3065     /* Validate Index */
3066     if (Index >= GL_LIMITS(clipplanes)) {
3067         TRACE("Application has requested clipplane this device doesn't support\n");
3068         return WINED3DERR_INVALIDCALL;
3069     }
3070
3071     This->updateStateBlock->changed.clipplane |= 1 << Index;
3072
3073     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
3074        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
3075        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
3076        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
3077         TRACE("Application is setting old values over, nothing to do\n");
3078         return WINED3D_OK;
3079     }
3080
3081     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3082     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3083     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3084     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3085
3086     /* Handle recording of state blocks */
3087     if (This->isRecordingState) {
3088         TRACE("Recording... not performing anything\n");
3089         return WINED3D_OK;
3090     }
3091
3092     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
3093
3094     return WINED3D_OK;
3095 }
3096
3097 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3098     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3099     TRACE("(%p) : for idx %d\n", This, Index);
3100
3101     /* Validate Index */
3102     if (Index >= GL_LIMITS(clipplanes)) {
3103         TRACE("Application has requested clipplane this device doesn't support\n");
3104         return WINED3DERR_INVALIDCALL;
3105     }
3106
3107     pPlane[0] = This->stateBlock->clipplane[Index][0];
3108     pPlane[1] = This->stateBlock->clipplane[Index][1];
3109     pPlane[2] = This->stateBlock->clipplane[Index][2];
3110     pPlane[3] = This->stateBlock->clipplane[Index][3];
3111     return WINED3D_OK;
3112 }
3113
3114 /*****
3115  * Get / Set Clip Plane Status
3116  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3117  *****/
3118 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3119     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3120     FIXME("(%p) : stub\n", This);
3121     if (NULL == pClipStatus) {
3122       return WINED3DERR_INVALIDCALL;
3123     }
3124     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3125     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3126     return WINED3D_OK;
3127 }
3128
3129 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3130     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3131     FIXME("(%p) : stub\n", This);
3132     if (NULL == pClipStatus) {
3133       return WINED3DERR_INVALIDCALL;
3134     }
3135     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3136     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3137     return WINED3D_OK;
3138 }
3139
3140 /*****
3141  * Get / Set Material
3142  *****/
3143 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3145
3146     This->updateStateBlock->changed.material = TRUE;
3147     This->updateStateBlock->material = *pMaterial;
3148
3149     /* Handle recording of state blocks */
3150     if (This->isRecordingState) {
3151         TRACE("Recording... not performing anything\n");
3152         return WINED3D_OK;
3153     }
3154
3155     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_MATERIAL);
3156     return WINED3D_OK;
3157 }
3158
3159 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3160     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3161     *pMaterial = This->updateStateBlock->material;
3162     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3163         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3164     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3165         pMaterial->Ambient.b, pMaterial->Ambient.a);
3166     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3167         pMaterial->Specular.b, pMaterial->Specular.a);
3168     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3169         pMaterial->Emissive.b, pMaterial->Emissive.a);
3170     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3171
3172     return WINED3D_OK;
3173 }
3174
3175 /*****
3176  * Get / Set Indices
3177  *****/
3178 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DBuffer* pIndexData, WINED3DFORMAT fmt) {
3179     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3180     IWineD3DBuffer *oldIdxs;
3181
3182     TRACE("(%p) : Setting to %p\n", This, pIndexData);
3183     oldIdxs = This->updateStateBlock->pIndexData;
3184
3185     This->updateStateBlock->changed.indices = TRUE;
3186     This->updateStateBlock->pIndexData = pIndexData;
3187     This->updateStateBlock->IndexFmt = fmt;
3188
3189     /* Handle recording of state blocks */
3190     if (This->isRecordingState) {
3191         TRACE("Recording... not performing anything\n");
3192         if(pIndexData) IWineD3DBuffer_AddRef(pIndexData);
3193         if(oldIdxs) IWineD3DBuffer_Release(oldIdxs);
3194         return WINED3D_OK;
3195     }
3196
3197     if(oldIdxs != pIndexData) {
3198         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
3199         if(pIndexData) {
3200             InterlockedIncrement(&((struct wined3d_buffer *)pIndexData)->bind_count);
3201             IWineD3DBuffer_AddRef(pIndexData);
3202         }
3203         if(oldIdxs) {
3204             InterlockedDecrement(&((struct wined3d_buffer *)oldIdxs)->bind_count);
3205             IWineD3DBuffer_Release(oldIdxs);
3206         }
3207     }
3208
3209     return WINED3D_OK;
3210 }
3211
3212 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DBuffer** ppIndexData) {
3213     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3214
3215     *ppIndexData = This->stateBlock->pIndexData;
3216
3217     /* up ref count on ppindexdata */
3218     if (*ppIndexData) {
3219         IWineD3DBuffer_AddRef(*ppIndexData);
3220         TRACE("(%p) index data set to %p\n", This, ppIndexData);
3221     }else{
3222         TRACE("(%p) No index data set\n", This);
3223     }
3224     TRACE("Returning %p\n", *ppIndexData);
3225
3226     return WINED3D_OK;
3227 }
3228
3229 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3230 static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, INT BaseIndex) {
3231     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3232     TRACE("(%p)->(%d)\n", This, BaseIndex);
3233
3234     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
3235         TRACE("Application is setting the old value over, nothing to do\n");
3236         return WINED3D_OK;
3237     }
3238
3239     This->updateStateBlock->baseVertexIndex = BaseIndex;
3240
3241     if (This->isRecordingState) {
3242         TRACE("Recording... not performing anything\n");
3243         return WINED3D_OK;
3244     }
3245     /* The base vertex index affects the stream sources */
3246     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
3247     return WINED3D_OK;
3248 }
3249
3250 static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, INT* base_index) {
3251     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3252     TRACE("(%p) : base_index %p\n", This, base_index);
3253
3254     *base_index = This->stateBlock->baseVertexIndex;
3255
3256     TRACE("Returning %u\n", *base_index);
3257
3258     return WINED3D_OK;
3259 }
3260
3261 /*****
3262  * Get / Set Viewports
3263  *****/
3264 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3265     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3266
3267     TRACE("(%p)\n", This);
3268     This->updateStateBlock->changed.viewport = TRUE;
3269     This->updateStateBlock->viewport = *pViewport;
3270
3271     /* Handle recording of state blocks */
3272     if (This->isRecordingState) {
3273         TRACE("Recording... not performing anything\n");
3274         return WINED3D_OK;
3275     }
3276
3277     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3278           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3279
3280     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
3281     return WINED3D_OK;
3282
3283 }
3284
3285 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3286     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3287     TRACE("(%p)\n", This);
3288     *pViewport = This->stateBlock->viewport;
3289     return WINED3D_OK;
3290 }
3291
3292 /*****
3293  * Get / Set Render States
3294  * TODO: Verify against dx9 definitions
3295  *****/
3296 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3297
3298     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
3299     DWORD oldValue = This->stateBlock->renderState[State];
3300
3301     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3302
3303     This->updateStateBlock->changed.renderState[State >> 5] |= 1 << (State & 0x1f);
3304     This->updateStateBlock->renderState[State] = Value;
3305
3306     /* Handle recording of state blocks */
3307     if (This->isRecordingState) {
3308         TRACE("Recording... not performing anything\n");
3309         return WINED3D_OK;
3310     }
3311
3312     /* Compared here and not before the assignment to allow proper stateblock recording */
3313     if(Value == oldValue) {
3314         TRACE("Application is setting the old value over, nothing to do\n");
3315     } else {
3316         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3317     }
3318
3319     return WINED3D_OK;
3320 }
3321
3322 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
3323     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3324     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
3325     *pValue = This->stateBlock->renderState[State];
3326     return WINED3D_OK;
3327 }
3328
3329 /*****
3330  * Get / Set Sampler States
3331  * TODO: Verify against dx9 definitions
3332  *****/
3333
3334 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3335     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3336     DWORD oldValue;
3337
3338     TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3339             This, Sampler, debug_d3dsamplerstate(Type), Type, Value);
3340
3341     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3342         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3343     }
3344
3345     if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) {
3346         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3347         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3348     }
3349     /**
3350     * SetSampler is designed to allow for more than the standard up to 8 textures
3351     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3352     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3353     *
3354     * http://developer.nvidia.com/object/General_FAQ.html#t6
3355     *
3356     * There are two new settings for GForce
3357     * the sampler one:
3358     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3359     * and the texture one:
3360     * GL_MAX_TEXTURE_COORDS_ARB.
3361     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3362      ******************/
3363
3364     oldValue = This->stateBlock->samplerState[Sampler][Type];
3365     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3366     This->updateStateBlock->changed.samplerState[Sampler] |= 1 << Type;
3367
3368     /* Handle recording of state blocks */
3369     if (This->isRecordingState) {
3370         TRACE("Recording... not performing anything\n");
3371         return WINED3D_OK;
3372     }
3373
3374     if(oldValue == Value) {
3375         TRACE("Application is setting the old value over, nothing to do\n");
3376         return WINED3D_OK;
3377     }
3378
3379     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3380
3381     return WINED3D_OK;
3382 }
3383
3384 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3385     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3386
3387     TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3388             This, Sampler, debug_d3dsamplerstate(Type), Type);
3389
3390     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3391         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3392     }
3393
3394     if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) {
3395         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3396         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3397     }
3398     *Value = This->stateBlock->samplerState[Sampler][Type];
3399     TRACE("(%p) : Returning %#x\n", This, *Value);
3400
3401     return WINED3D_OK;
3402 }
3403
3404 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3405     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3406
3407     This->updateStateBlock->changed.scissorRect = TRUE;
3408     if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
3409         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
3410         return WINED3D_OK;
3411     }
3412     CopyRect(&This->updateStateBlock->scissorRect, pRect);
3413
3414     if(This->isRecordingState) {
3415         TRACE("Recording... not performing anything\n");
3416         return WINED3D_OK;
3417     }
3418
3419     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
3420
3421     return WINED3D_OK;
3422 }
3423
3424 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3425     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3426
3427     *pRect = This->updateStateBlock->scissorRect;
3428     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3429     return WINED3D_OK;
3430 }
3431
3432 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3433     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3434     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3435
3436     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3437
3438     This->updateStateBlock->vertexDecl = pDecl;
3439     This->updateStateBlock->changed.vertexDecl = TRUE;
3440
3441     if (This->isRecordingState) {
3442         TRACE("Recording... not performing anything\n");
3443         return WINED3D_OK;
3444     } else if(pDecl == oldDecl) {
3445         /* Checked after the assignment to allow proper stateblock recording */
3446         TRACE("Application is setting the old declaration over, nothing to do\n");
3447         return WINED3D_OK;
3448     }
3449
3450     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3451     return WINED3D_OK;
3452 }
3453
3454 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3455     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3456
3457     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3458
3459     *ppDecl = This->stateBlock->vertexDecl;
3460     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3461     return WINED3D_OK;
3462 }
3463
3464 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3465     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3466     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3467
3468     This->updateStateBlock->vertexShader         = pShader;
3469     This->updateStateBlock->changed.vertexShader = TRUE;
3470
3471     if (This->isRecordingState) {
3472         if(pShader) IWineD3DVertexShader_AddRef(pShader);
3473         if(oldShader) IWineD3DVertexShader_Release(oldShader);
3474         TRACE("Recording... not performing anything\n");
3475         return WINED3D_OK;
3476     } else if(oldShader == pShader) {
3477         /* Checked here to allow proper stateblock recording */
3478         TRACE("App is setting the old shader over, nothing to do\n");
3479         return WINED3D_OK;
3480     }
3481
3482     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3483     if(pShader) IWineD3DVertexShader_AddRef(pShader);
3484     if(oldShader) IWineD3DVertexShader_Release(oldShader);
3485
3486     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3487
3488     return WINED3D_OK;
3489 }
3490
3491 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3492     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3493
3494     if (NULL == ppShader) {
3495         return WINED3DERR_INVALIDCALL;
3496     }
3497     *ppShader = This->stateBlock->vertexShader;
3498     if( NULL != *ppShader)
3499         IWineD3DVertexShader_AddRef(*ppShader);
3500
3501     TRACE("(%p) : returning %p\n", This, *ppShader);
3502     return WINED3D_OK;
3503 }
3504
3505 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3506     IWineD3DDevice *iface,
3507     UINT start,
3508     CONST BOOL *srcData,
3509     UINT count) {
3510
3511     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3512     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3513
3514     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3515             iface, srcData, start, count);
3516
3517     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3518
3519     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3520     for (i = 0; i < cnt; i++)
3521         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3522
3523     for (i = start; i < cnt + start; ++i) {
3524         This->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
3525     }
3526
3527     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3528
3529     return WINED3D_OK;
3530 }
3531
3532 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3533     IWineD3DDevice *iface,
3534     UINT start,
3535     BOOL *dstData,
3536     UINT count) {
3537
3538     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3539     int cnt = min(count, MAX_CONST_B - start);
3540
3541     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3542             iface, dstData, start, count);
3543
3544     if (dstData == NULL || cnt < 0)
3545         return WINED3DERR_INVALIDCALL;
3546
3547     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3548     return WINED3D_OK;
3549 }
3550
3551 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3552     IWineD3DDevice *iface,
3553     UINT start,
3554     CONST int *srcData,
3555     UINT count) {
3556
3557     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3558     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3559
3560     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3561             iface, srcData, start, count);
3562
3563     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3564
3565     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3566     for (i = 0; i < cnt; i++)
3567         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3568            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3569
3570     for (i = start; i < cnt + start; ++i) {
3571         This->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
3572     }
3573
3574     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3575
3576     return WINED3D_OK;
3577 }
3578
3579 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3580     IWineD3DDevice *iface,
3581     UINT start,
3582     int *dstData,
3583     UINT count) {
3584
3585     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3586     int cnt = min(count, MAX_CONST_I - start);
3587
3588     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3589             iface, dstData, start, count);
3590
3591     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3592         return WINED3DERR_INVALIDCALL;
3593
3594     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3595     return WINED3D_OK;
3596 }
3597
3598 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3599     IWineD3DDevice *iface,
3600     UINT start,
3601     CONST float *srcData,
3602     UINT count) {
3603
3604     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3605     UINT i;
3606
3607     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3608             iface, srcData, start, count);
3609
3610     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3611     if (srcData == NULL || start + count > This->d3d_vshader_constantF || start > This->d3d_vshader_constantF)
3612         return WINED3DERR_INVALIDCALL;
3613
3614     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3615     if(TRACE_ON(d3d)) {
3616         for (i = 0; i < count; i++)
3617             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3618                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3619     }
3620
3621     if (!This->isRecordingState)
3622     {
3623         This->shader_backend->shader_update_float_vertex_constants(iface, start, count);
3624         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3625     }
3626
3627     memset(This->updateStateBlock->changed.vertexShaderConstantsF + start, 1,
3628             sizeof(*This->updateStateBlock->changed.vertexShaderConstantsF) * count);
3629
3630     return WINED3D_OK;
3631 }
3632
3633 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3634     IWineD3DDevice *iface,
3635     UINT start,
3636     float *dstData,
3637     UINT count) {
3638
3639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3640     int cnt = min(count, This->d3d_vshader_constantF - start);
3641
3642     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3643             iface, dstData, start, count);
3644
3645     if (dstData == NULL || cnt < 0)
3646         return WINED3DERR_INVALIDCALL;
3647
3648     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3649     return WINED3D_OK;
3650 }
3651
3652 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3653     DWORD i;
3654     for(i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
3655     {
3656         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3657     }
3658 }
3659
3660 static void device_map_stage(IWineD3DDeviceImpl *This, int stage, int unit) {
3661     int i = This->rev_tex_unit_map[unit];
3662     int j = This->texUnitMap[stage];
3663
3664     This->texUnitMap[stage] = unit;
3665     if (i != -1 && i != stage) {
3666         This->texUnitMap[i] = -1;
3667     }
3668
3669     This->rev_tex_unit_map[unit] = stage;
3670     if (j != -1 && j != unit) {
3671         This->rev_tex_unit_map[j] = -1;
3672     }
3673 }
3674
3675 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
3676     int i;
3677
3678     This->fixed_function_usage_map = 0;
3679     for (i = 0; i < MAX_TEXTURES; ++i) {
3680         WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP];
3681         WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP];
3682         DWORD color_arg1 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG1] & WINED3DTA_SELECTMASK;
3683         DWORD color_arg2 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG2] & WINED3DTA_SELECTMASK;
3684         DWORD color_arg3 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG0] & WINED3DTA_SELECTMASK;
3685         DWORD alpha_arg1 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1] & WINED3DTA_SELECTMASK;
3686         DWORD alpha_arg2 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2] & WINED3DTA_SELECTMASK;
3687         DWORD alpha_arg3 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0] & WINED3DTA_SELECTMASK;
3688
3689         if (color_op == WINED3DTOP_DISABLE) {
3690             /* Not used, and disable higher stages */
3691             break;
3692         }
3693
3694         if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG2)
3695                 || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG1)
3696                 || ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP))
3697                 || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
3698                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
3699                 || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
3700             This->fixed_function_usage_map |= (1 << i);
3701         }
3702
3703         if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
3704             This->fixed_function_usage_map |= (1 << (i + 1));
3705         }
3706     }
3707 }
3708
3709 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
3710     unsigned int i, tex;
3711     WORD ffu_map;
3712
3713     device_update_fixed_function_usage_map(This);
3714     ffu_map = This->fixed_function_usage_map;
3715
3716     if (This->max_ffp_textures == This->max_ffp_texture_stages ||
3717             This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
3718         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3719         {
3720             if (!(ffu_map & 1)) continue;
3721
3722             if (This->texUnitMap[i] != i) {
3723                 device_map_stage(This, i, i);
3724                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3725                 markTextureStagesDirty(This, i);
3726             }
3727         }
3728         return;
3729     }
3730
3731     /* Now work out the mapping */
3732     tex = 0;
3733     for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3734     {
3735         if (!(ffu_map & 1)) continue;
3736
3737         if (This->texUnitMap[i] != tex) {
3738             device_map_stage(This, i, tex);
3739             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3740             markTextureStagesDirty(This, i);
3741         }
3742
3743         ++tex;
3744     }
3745 }
3746
3747 static void device_map_psamplers(IWineD3DDeviceImpl *This) {
3748     const WINED3DSAMPLER_TEXTURE_TYPE *sampler_type =
3749             ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.sampler_type;
3750     unsigned int i;
3751
3752     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
3753         if (sampler_type[i] && This->texUnitMap[i] != i)
3754         {
3755             device_map_stage(This, i, i);
3756             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3757             if (i < MAX_TEXTURES) {
3758                 markTextureStagesDirty(This, i);
3759             }
3760         }
3761     }
3762 }
3763
3764 static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshader_sampler_tokens,
3765         const DWORD *vshader_sampler_tokens, int unit)
3766 {
3767     int current_mapping = This->rev_tex_unit_map[unit];
3768
3769     if (current_mapping == -1) {
3770         /* Not currently used */
3771         return TRUE;
3772     }
3773
3774     if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
3775         /* Used by a fragment sampler */
3776
3777         if (!pshader_sampler_tokens) {
3778             /* No pixel shader, check fixed function */
3779             return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping));
3780         }
3781
3782         /* Pixel shader, check the shader's sampler map */
3783         return !pshader_sampler_tokens[current_mapping];
3784     }
3785
3786     /* Used by a vertex sampler */
3787     return !vshader_sampler_tokens[current_mapping];
3788 }
3789
3790 static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
3791     const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_type =
3792             ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.sampler_type;
3793     const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_type = NULL;
3794     int start = GL_LIMITS(combined_samplers) - 1;
3795     int i;
3796
3797     if (ps) {
3798         IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
3799
3800         /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3801          * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3802         pshader_sampler_type = pshader->baseShader.reg_maps.sampler_type;
3803     }
3804
3805     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
3806         int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
3807         if (vshader_sampler_type[i])
3808         {
3809             if (This->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
3810             {
3811                 /* Already mapped somewhere */
3812                 continue;
3813             }
3814
3815             while (start >= 0) {
3816                 if (device_unit_free_for_vs(This, pshader_sampler_type, vshader_sampler_type, start))
3817                 {
3818                     device_map_stage(This, vsampler_idx, start);
3819                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx));
3820
3821                     --start;
3822                     break;
3823                 }
3824
3825                 --start;
3826             }
3827         }
3828     }
3829 }
3830
3831 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3832     BOOL vs = use_vs(This->stateBlock);
3833     BOOL ps = use_ps(This->stateBlock);
3834     /*
3835      * Rules are:
3836      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3837      * that would be really messy and require shader recompilation
3838      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3839      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3840      */
3841     if (ps) {
3842         device_map_psamplers(This);
3843     } else {
3844         device_map_fixed_function_samplers(This);
3845     }
3846
3847     if (vs) {
3848         device_map_vsamplers(This, ps);
3849     }
3850 }
3851
3852 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3853     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3854     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3855     This->updateStateBlock->pixelShader         = pShader;
3856     This->updateStateBlock->changed.pixelShader = TRUE;
3857
3858     /* Handle recording of state blocks */
3859     if (This->isRecordingState) {
3860         TRACE("Recording... not performing anything\n");
3861     }
3862
3863     if (This->isRecordingState) {
3864         TRACE("Recording... not performing anything\n");
3865         if(pShader) IWineD3DPixelShader_AddRef(pShader);
3866         if(oldShader) IWineD3DPixelShader_Release(oldShader);
3867         return WINED3D_OK;
3868     }
3869
3870     if(pShader == oldShader) {
3871         TRACE("App is setting the old pixel shader over, nothing to do\n");
3872         return WINED3D_OK;
3873     }
3874
3875     if(pShader) IWineD3DPixelShader_AddRef(pShader);
3876     if(oldShader) IWineD3DPixelShader_Release(oldShader);
3877
3878     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3879     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3880
3881     return WINED3D_OK;
3882 }
3883
3884 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3885     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3886
3887     if (NULL == ppShader) {
3888         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3889         return WINED3DERR_INVALIDCALL;
3890     }
3891
3892     *ppShader =  This->stateBlock->pixelShader;
3893     if (NULL != *ppShader) {
3894         IWineD3DPixelShader_AddRef(*ppShader);
3895     }
3896     TRACE("(%p) : returning %p\n", This, *ppShader);
3897     return WINED3D_OK;
3898 }
3899
3900 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3901     IWineD3DDevice *iface,
3902     UINT start,
3903     CONST BOOL *srcData,
3904     UINT count) {
3905
3906     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3907     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3908
3909     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3910             iface, srcData, start, count);
3911
3912     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3913
3914     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3915     for (i = 0; i < cnt; i++)
3916         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3917
3918     for (i = start; i < cnt + start; ++i) {
3919         This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
3920     }
3921
3922     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3923
3924     return WINED3D_OK;
3925 }
3926
3927 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3928     IWineD3DDevice *iface,
3929     UINT start,
3930     BOOL *dstData,
3931     UINT count) {
3932
3933     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3934     int cnt = min(count, MAX_CONST_B - start);
3935
3936     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3937             iface, dstData, start, count);
3938
3939     if (dstData == NULL || cnt < 0)
3940         return WINED3DERR_INVALIDCALL;
3941
3942     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3943     return WINED3D_OK;
3944 }
3945
3946 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3947     IWineD3DDevice *iface,
3948     UINT start,
3949     CONST int *srcData,
3950     UINT count) {
3951
3952     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3953     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3954
3955     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3956             iface, srcData, start, count);
3957
3958     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3959
3960     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3961     for (i = 0; i < cnt; i++)
3962         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3963            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3964
3965     for (i = start; i < cnt + start; ++i) {
3966         This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
3967     }
3968
3969     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3970
3971     return WINED3D_OK;
3972 }
3973
3974 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3975     IWineD3DDevice *iface,
3976     UINT start,
3977     int *dstData,
3978     UINT count) {
3979
3980     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3981     int cnt = min(count, MAX_CONST_I - start);
3982
3983     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3984             iface, dstData, start, count);
3985
3986     if (dstData == NULL || cnt < 0)
3987         return WINED3DERR_INVALIDCALL;
3988
3989     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3990     return WINED3D_OK;
3991 }
3992
3993 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3994     IWineD3DDevice *iface,
3995     UINT start,
3996     CONST float *srcData,
3997     UINT count) {
3998
3999     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4000     UINT i;
4001
4002     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4003             iface, srcData, start, count);
4004
4005     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
4006     if (srcData == NULL || start + count > This->d3d_pshader_constantF || start > This->d3d_pshader_constantF)
4007         return WINED3DERR_INVALIDCALL;
4008
4009     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
4010     if(TRACE_ON(d3d)) {
4011         for (i = 0; i < count; i++)
4012             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4013                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4014     }
4015
4016     if (!This->isRecordingState)
4017     {
4018         This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
4019         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
4020     }
4021
4022     memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
4023             sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
4024
4025     return WINED3D_OK;
4026 }
4027
4028 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4029     IWineD3DDevice *iface,
4030     UINT start,
4031     float *dstData,
4032     UINT count) {
4033
4034     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4035     int cnt = min(count, This->d3d_pshader_constantF - start);
4036
4037     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4038             iface, dstData, start, count);
4039
4040     if (dstData == NULL || cnt < 0)
4041         return WINED3DERR_INVALIDCALL;
4042
4043     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4044     return WINED3D_OK;
4045 }
4046
4047 /* Context activation is done by the caller. */
4048 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4049 static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount,
4050         const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD dwFlags,
4051         DWORD DestFVF)
4052 {
4053     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
4054     unsigned int i;
4055     WINED3DVIEWPORT vp;
4056     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
4057     BOOL doClip;
4058     DWORD numTextures;
4059
4060     if (stream_info->elements[WINED3D_FFP_NORMAL].data)
4061     {
4062         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4063     }
4064
4065     if (!stream_info->elements[WINED3D_FFP_POSITION].data)
4066     {
4067         ERR("Source has no position mask\n");
4068         return WINED3DERR_INVALIDCALL;
4069     }
4070
4071     /* We might access VBOs from this code, so hold the lock */
4072     ENTER_GL();
4073
4074     if (dest->resource.allocatedMemory == NULL) {
4075         buffer_get_sysmem(dest);
4076     }
4077
4078     /* Get a pointer into the destination vbo(create one if none exists) and
4079      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4080      */
4081     if (!dest->buffer_object && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT))
4082     {
4083         dest->flags |= WINED3D_BUFFER_CREATEBO;
4084         IWineD3DBuffer_PreLoad((IWineD3DBuffer *)dest);
4085     }
4086
4087     if (dest->buffer_object)
4088     {
4089         unsigned char extrabytes = 0;
4090         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
4091          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
4092          * this may write 4 extra bytes beyond the area that should be written
4093          */
4094         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
4095         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
4096         if(!dest_conv_addr) {
4097             ERR("Out of memory\n");
4098             /* Continue without storing converted vertices */
4099         }
4100         dest_conv = dest_conv_addr;
4101     }
4102
4103     /* Should I clip?
4104      * a) WINED3DRS_CLIPPING is enabled
4105      * b) WINED3DVOP_CLIP is passed
4106      */
4107     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4108         static BOOL warned = FALSE;
4109         /*
4110          * The clipping code is not quite correct. Some things need
4111          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4112          * so disable clipping for now.
4113          * (The graphics in Half-Life are broken, and my processvertices
4114          *  test crashes with IDirect3DDevice3)
4115         doClip = TRUE;
4116          */
4117         doClip = FALSE;
4118         if(!warned) {
4119            warned = TRUE;
4120            FIXME("Clipping is broken and disabled for now\n");
4121         }
4122     } else doClip = FALSE;
4123     dest_ptr = ((char *) buffer_get_sysmem(dest)) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4124
4125     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4126                                  WINED3DTS_VIEW,
4127                                  &view_mat);
4128     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4129                                  WINED3DTS_PROJECTION,
4130                                  &proj_mat);
4131     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4132                                  WINED3DTS_WORLDMATRIX(0),
4133                                  &world_mat);
4134
4135     TRACE("View mat:\n");
4136     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);
4137     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);
4138     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);
4139     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);
4140
4141     TRACE("Proj mat:\n");
4142     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);
4143     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);
4144     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);
4145     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);
4146
4147     TRACE("World mat:\n");
4148     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);
4149     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);
4150     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);
4151     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);
4152
4153     /* Get the viewport */
4154     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4155     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4156           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4157
4158     multiply_matrix(&mat,&view_mat,&world_mat);
4159     multiply_matrix(&mat,&proj_mat,&mat);
4160
4161     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
4162
4163     for (i = 0; i < dwCount; i+= 1) {
4164         unsigned int tex_index;
4165
4166         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
4167              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
4168             /* The position first */
4169             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
4170             const float *p = (const float *)(element->data + i * element->stride);
4171             float x, y, z, rhw;
4172             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4173
4174             /* Multiplication with world, view and projection matrix */
4175             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);
4176             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);
4177             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);
4178             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);
4179
4180             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4181
4182             /* WARNING: The following things are taken from d3d7 and were not yet checked
4183              * against d3d8 or d3d9!
4184              */
4185
4186             /* Clipping conditions: From msdn
4187              *
4188              * A vertex is clipped if it does not match the following requirements
4189              * -rhw < x <= rhw
4190              * -rhw < y <= rhw
4191              *    0 < z <= rhw
4192              *    0 < rhw ( Not in d3d7, but tested in d3d7)
4193              *
4194              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4195              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4196              *
4197              */
4198
4199             if( !doClip ||
4200                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4201                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
4202                   ( rhw > eps ) ) ) {
4203
4204                 /* "Normal" viewport transformation (not clipped)
4205                  * 1) The values are divided by rhw
4206                  * 2) The y axis is negative, so multiply it with -1
4207                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4208                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4209                  * 4) Multiply x with Width/2 and add Width/2
4210                  * 5) The same for the height
4211                  * 6) Add the viewpoint X and Y to the 2D coordinates and
4212                  *    The minimum Z value to z
4213                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4214                  *
4215                  * Well, basically it's simply a linear transformation into viewport
4216                  * coordinates
4217                  */
4218
4219                 x /= rhw;
4220                 y /= rhw;
4221                 z /= rhw;
4222
4223                 y *= -1;
4224
4225                 x *= vp.Width / 2;
4226                 y *= vp.Height / 2;
4227                 z *= vp.MaxZ - vp.MinZ;
4228
4229                 x += vp.Width / 2 + vp.X;
4230                 y += vp.Height / 2 + vp.Y;
4231                 z += vp.MinZ;
4232
4233                 rhw = 1 / rhw;
4234             } else {
4235                 /* That vertex got clipped
4236                  * Contrary to OpenGL it is not dropped completely, it just
4237                  * undergoes a different calculation.
4238                  */
4239                 TRACE("Vertex got clipped\n");
4240                 x += rhw;
4241                 y += rhw;
4242
4243                 x  /= 2;
4244                 y  /= 2;
4245
4246                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4247                  * outside of the main vertex buffer memory. That needs some more
4248                  * investigation...
4249                  */
4250             }
4251
4252             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4253
4254
4255             ( (float *) dest_ptr)[0] = x;
4256             ( (float *) dest_ptr)[1] = y;
4257             ( (float *) dest_ptr)[2] = z;
4258             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4259
4260             dest_ptr += 3 * sizeof(float);
4261
4262             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4263                 dest_ptr += sizeof(float);
4264             }
4265
4266             if(dest_conv) {
4267                 float w = 1 / rhw;
4268                 ( (float *) dest_conv)[0] = x * w;
4269                 ( (float *) dest_conv)[1] = y * w;
4270                 ( (float *) dest_conv)[2] = z * w;
4271                 ( (float *) dest_conv)[3] = w;
4272
4273                 dest_conv += 3 * sizeof(float);
4274
4275                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4276                     dest_conv += sizeof(float);
4277                 }
4278             }
4279         }
4280         if (DestFVF & WINED3DFVF_PSIZE) {
4281             dest_ptr += sizeof(DWORD);
4282             if(dest_conv) dest_conv += sizeof(DWORD);
4283         }
4284         if (DestFVF & WINED3DFVF_NORMAL) {
4285             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
4286             const float *normal = (const float *)(element->data + i * element->stride);
4287             /* AFAIK this should go into the lighting information */
4288             FIXME("Didn't expect the destination to have a normal\n");
4289             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4290             if(dest_conv) {
4291                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4292             }
4293         }
4294
4295         if (DestFVF & WINED3DFVF_DIFFUSE) {
4296             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
4297             const DWORD *color_d = (const DWORD *)(element->data + i * element->stride);
4298             if(!color_d) {
4299                 static BOOL warned = FALSE;
4300
4301                 if(!warned) {
4302                     ERR("No diffuse color in source, but destination has one\n");
4303                     warned = TRUE;
4304                 }
4305
4306                 *( (DWORD *) dest_ptr) = 0xffffffff;
4307                 dest_ptr += sizeof(DWORD);
4308
4309                 if(dest_conv) {
4310                     *( (DWORD *) dest_conv) = 0xffffffff;
4311                     dest_conv += sizeof(DWORD);
4312                 }
4313             }
4314             else {
4315                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4316                 if(dest_conv) {
4317                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4318                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4319                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4320                     dest_conv += sizeof(DWORD);
4321                 }
4322             }
4323         }
4324
4325         if (DestFVF & WINED3DFVF_SPECULAR) { 
4326             /* What's the color value in the feedback buffer? */
4327             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
4328             const DWORD *color_s = (const DWORD *)(element->data + i * element->stride);
4329             if(!color_s) {
4330                 static BOOL warned = FALSE;
4331
4332                 if(!warned) {
4333                     ERR("No specular color in source, but destination has one\n");
4334                     warned = TRUE;
4335                 }
4336
4337                 *( (DWORD *) dest_ptr) = 0xFF000000;
4338                 dest_ptr += sizeof(DWORD);
4339
4340                 if(dest_conv) {
4341                     *( (DWORD *) dest_conv) = 0xFF000000;
4342                     dest_conv += sizeof(DWORD);
4343                 }
4344             }
4345             else {
4346                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4347                 if(dest_conv) {
4348                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4349                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4350                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4351                     dest_conv += sizeof(DWORD);
4352                 }
4353             }
4354         }
4355
4356         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4357             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
4358             const float *tex_coord = (const float *)(element->data + i * element->stride);
4359             if(!tex_coord) {
4360                 ERR("No source texture, but destination requests one\n");
4361                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4362                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4363             }
4364             else {
4365                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4366                 if(dest_conv) {
4367                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4368                 }
4369             }
4370         }
4371     }
4372
4373     if(dest_conv) {
4374         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->buffer_object));
4375         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4376         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
4377                                       dwCount * get_flexible_vertex_size(DestFVF),
4378                                       dest_conv_addr));
4379         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4380         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
4381     }
4382
4383     LEAVE_GL();
4384
4385     return WINED3D_OK;
4386 }
4387 #undef copy_and_next
4388
4389 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex,
4390         UINT VertexCount, IWineD3DBuffer *pDestBuffer, IWineD3DVertexDeclaration *pVertexDecl, DWORD Flags,
4391         DWORD DestFVF)
4392 {
4393     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4394     struct wined3d_stream_info stream_info;
4395     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
4396     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4397
4398     if(pVertexDecl) {
4399         ERR("Output vertex declaration not implemented yet\n");
4400     }
4401
4402     /* Need any context to write to the vbo. */
4403     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4404
4405     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4406      * control the streamIsUP flag, thus restore it afterwards.
4407      */
4408     This->stateBlock->streamIsUP = FALSE;
4409     device_stream_info_from_declaration(This, FALSE, &stream_info, &vbo);
4410     This->stateBlock->streamIsUP = streamWasUP;
4411
4412     if(vbo || SrcStartIndex) {
4413         unsigned int i;
4414         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4415          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4416          *
4417          * Also get the start index in, but only loop over all elements if there's something to add at all.
4418          */
4419         for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
4420         {
4421             struct wined3d_stream_info_element *e = &stream_info.elements[i];
4422             if (e->buffer_object)
4423             {
4424                 struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx];
4425                 e->buffer_object = 0;
4426                 e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb));
4427                 ENTER_GL();
4428                 GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
4429                 vb->buffer_object = 0;
4430                 LEAVE_GL();
4431             }
4432             if (e->data) e->data += e->stride * SrcStartIndex;
4433         }
4434     }
4435
4436     return process_vertices_strided(This, DestIndex, VertexCount, &stream_info,
4437             (struct wined3d_buffer *)pDestBuffer, Flags, DestFVF);
4438 }
4439
4440 /*****
4441  * Get / Set Texture Stage States
4442  * TODO: Verify against dx9 definitions
4443  *****/
4444 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4445     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4446     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4447
4448     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4449
4450     if (Stage >= MAX_TEXTURES) {
4451         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
4452         return WINED3D_OK;
4453     }
4454
4455     This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
4456     This->updateStateBlock->textureState[Stage][Type]         = Value;
4457
4458     if (This->isRecordingState) {
4459         TRACE("Recording... not performing anything\n");
4460         return WINED3D_OK;
4461     }
4462
4463     /* Checked after the assignments to allow proper stateblock recording */
4464     if(oldValue == Value) {
4465         TRACE("App is setting the old value over, nothing to do\n");
4466         return WINED3D_OK;
4467     }
4468
4469     if(Stage > This->stateBlock->lowest_disabled_stage &&
4470        This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4471         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4472          * Changes in other states are important on disabled stages too
4473          */
4474         return WINED3D_OK;
4475     }
4476
4477     if(Type == WINED3DTSS_COLOROP) {
4478         unsigned int i;
4479
4480         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4481             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4482              * they have to be disabled
4483              *
4484              * The current stage is dirtified below.
4485              */
4486             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4487                 TRACE("Additionally dirtifying stage %u\n", i);
4488                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4489             }
4490             This->stateBlock->lowest_disabled_stage = Stage;
4491             TRACE("New lowest disabled: %u\n", Stage);
4492         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4493             /* Previously disabled stage enabled. Stages above it may need enabling
4494              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4495              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4496              *
4497              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4498              */
4499
4500             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4501                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4502                     break;
4503                 }
4504                 TRACE("Additionally dirtifying stage %u due to enable\n", i);
4505                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4506             }
4507             This->stateBlock->lowest_disabled_stage = i;
4508             TRACE("New lowest disabled: %u\n", i);
4509         }
4510     }
4511
4512     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4513
4514     return WINED3D_OK;
4515 }
4516
4517 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4518     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4519     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4520     *pValue = This->updateStateBlock->textureState[Stage][Type];
4521     return WINED3D_OK;
4522 }
4523
4524 /*****
4525  * Get / Set Texture
4526  *****/
4527 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4528     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4529     IWineD3DBaseTexture *oldTexture;
4530
4531     TRACE("(%p) : Stage %#x, Texture %p\n", This, Stage, pTexture);
4532
4533     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4534         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4535     }
4536
4537     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4538         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4539         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4540     }
4541
4542     oldTexture = This->updateStateBlock->textures[Stage];
4543
4544     /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4545     if (pTexture && ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH)
4546     {
4547         WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4548         return WINED3DERR_INVALIDCALL;
4549     }
4550
4551     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4552     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4553
4554     This->updateStateBlock->changed.textures |= 1 << Stage;
4555     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4556     This->updateStateBlock->textures[Stage]         = pTexture;
4557
4558     /* Handle recording of state blocks */
4559     if (This->isRecordingState) {
4560         TRACE("Recording... not performing anything\n");
4561         return WINED3D_OK;
4562     }
4563
4564     if(oldTexture == pTexture) {
4565         TRACE("App is setting the same texture again, nothing to do\n");
4566         return WINED3D_OK;
4567     }
4568
4569     /** NOTE: MSDN says that setTexture increases the reference count,
4570     * and that the application must set the texture back to null (or have a leaky application),
4571     * This means we should pass the refcount up to the parent
4572      *******************************/
4573     if (NULL != This->updateStateBlock->textures[Stage]) {
4574         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4575         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4576         UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4577
4578         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4579
4580         if (!oldTexture || dimensions != IWineD3DBaseTexture_GetTextureDimensions(oldTexture))
4581         {
4582             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
4583         }
4584
4585         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4586             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4587              * so the COLOROP and ALPHAOP have to be dirtified.
4588              */
4589             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4590             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4591         }
4592         if(bindCount == 1) {
4593             new->baseTexture.sampler = Stage;
4594         }
4595         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4596
4597     }
4598
4599     if (NULL != oldTexture) {
4600         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4601         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4602
4603         IWineD3DBaseTexture_Release(oldTexture);
4604         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4605             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4606             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4607         }
4608
4609         if(bindCount && old->baseTexture.sampler == Stage) {
4610             int i;
4611             /* Have to do a search for the other sampler(s) where the texture is bound to
4612              * Shouldn't happen as long as apps bind a texture only to one stage
4613              */
4614             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4615             for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
4616                 if(This->updateStateBlock->textures[i] == oldTexture) {
4617                     old->baseTexture.sampler = i;
4618                     break;
4619                 }
4620             }
4621         }
4622     }
4623
4624     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4625
4626     return WINED3D_OK;
4627 }
4628
4629 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4630     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4631
4632     TRACE("(%p) : Stage %#x, ppTexture %p\n", This, Stage, ppTexture);
4633
4634     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4635         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4636     }
4637
4638     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4639         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4640         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4641     }
4642
4643     *ppTexture=This->stateBlock->textures[Stage];
4644     if (*ppTexture)
4645         IWineD3DBaseTexture_AddRef(*ppTexture);
4646
4647     TRACE("(%p) : Returning %p\n", This, *ppTexture);
4648
4649     return WINED3D_OK;
4650 }
4651
4652 /*****
4653  * Get Back Buffer
4654  *****/
4655 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4656                                                 IWineD3DSurface **ppBackBuffer) {
4657     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4658     IWineD3DSwapChain *swapChain;
4659     HRESULT hr;
4660
4661     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4662
4663     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4664     if (hr == WINED3D_OK) {
4665         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4666             IWineD3DSwapChain_Release(swapChain);
4667     } else {
4668         *ppBackBuffer = NULL;
4669     }
4670     return hr;
4671 }
4672
4673 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4674     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4675     WARN("(%p) : stub, calling idirect3d for now\n", This);
4676     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4677 }
4678
4679 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4680     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4681     IWineD3DSwapChain *swapChain;
4682     HRESULT hr;
4683
4684     if(iSwapChain > 0) {
4685         hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4686         if (hr == WINED3D_OK) {
4687             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4688             IWineD3DSwapChain_Release(swapChain);
4689         } else {
4690             FIXME("(%p) Error getting display mode\n", This);
4691         }
4692     } else {
4693         /* Don't read the real display mode,
4694            but return the stored mode instead. X11 can't change the color
4695            depth, and some apps are pretty angry if they SetDisplayMode from
4696            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4697
4698            Also don't relay to the swapchain because with ddraw it's possible
4699            that there isn't a swapchain at all */
4700         pMode->Width = This->ddraw_width;
4701         pMode->Height = This->ddraw_height;
4702         pMode->Format = This->ddraw_format;
4703         pMode->RefreshRate = 0;
4704         hr = WINED3D_OK;
4705     }
4706
4707     return hr;
4708 }
4709
4710 /*****
4711  * Stateblock related functions
4712  *****/
4713
4714 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4715     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4716     IWineD3DStateBlock *stateblock;
4717     HRESULT hr;
4718
4719     TRACE("(%p)\n", This);
4720
4721     if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
4722
4723     hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock, NULL);
4724     if (FAILED(hr)) return hr;
4725
4726     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4727     This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
4728     This->isRecordingState = TRUE;
4729
4730     TRACE("(%p) recording stateblock %p\n", This, stateblock);
4731
4732     return WINED3D_OK;
4733 }
4734
4735 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4736     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4737     unsigned int i, j;
4738     IWineD3DStateBlockImpl *object = This->updateStateBlock;
4739
4740     if (!This->isRecordingState) {
4741         WARN("(%p) not recording! returning error\n", This);
4742         *ppStateBlock = NULL;
4743         return WINED3DERR_INVALIDCALL;
4744     }
4745
4746     for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
4747     {
4748         DWORD map = object->changed.renderState[i];
4749         for (j = 0; map; map >>= 1, ++j)
4750         {
4751             if (!(map & 1)) continue;
4752
4753             object->contained_render_states[object->num_contained_render_states++] = (i << 5) | j;
4754         }
4755     }
4756
4757     for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
4758     {
4759         DWORD map = object->changed.transform[i];
4760         for (j = 0; map; map >>= 1, ++j)
4761         {
4762             if (!(map & 1)) continue;
4763
4764             object->contained_transform_states[object->num_contained_transform_states++] = (i << 5) | j;
4765         }
4766     }
4767     for(i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
4768         if(object->changed.vertexShaderConstantsF[i]) {
4769             object->contained_vs_consts_f[object->num_contained_vs_consts_f] = i;
4770             object->num_contained_vs_consts_f++;
4771         }
4772     }
4773     for(i = 0; i < MAX_CONST_I; i++) {
4774         if (object->changed.vertexShaderConstantsI & (1 << i))
4775         {
4776             object->contained_vs_consts_i[object->num_contained_vs_consts_i] = i;
4777             object->num_contained_vs_consts_i++;
4778         }
4779     }
4780     for(i = 0; i < MAX_CONST_B; i++) {
4781         if (object->changed.vertexShaderConstantsB & (1 << i))
4782         {
4783             object->contained_vs_consts_b[object->num_contained_vs_consts_b] = i;
4784             object->num_contained_vs_consts_b++;
4785         }
4786     }
4787     for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
4788     {
4789         if (object->changed.pixelShaderConstantsF[i])
4790         {
4791             object->contained_ps_consts_f[object->num_contained_ps_consts_f] = i;
4792             ++object->num_contained_ps_consts_f;
4793         }
4794     }
4795     for(i = 0; i < MAX_CONST_I; i++) {
4796         if (object->changed.pixelShaderConstantsI & (1 << i))
4797         {
4798             object->contained_ps_consts_i[object->num_contained_ps_consts_i] = i;
4799             object->num_contained_ps_consts_i++;
4800         }
4801     }
4802     for(i = 0; i < MAX_CONST_B; i++) {
4803         if (object->changed.pixelShaderConstantsB & (1 << i))
4804         {
4805             object->contained_ps_consts_b[object->num_contained_ps_consts_b] = i;
4806             object->num_contained_ps_consts_b++;
4807         }
4808     }
4809     for(i = 0; i < MAX_TEXTURES; i++) {
4810         DWORD map = object->changed.textureState[i];
4811
4812         for(j = 0; map; map >>= 1, ++j)
4813         {
4814             if (!(map & 1)) continue;
4815
4816             object->contained_tss_states[object->num_contained_tss_states].stage = i;
4817             object->contained_tss_states[object->num_contained_tss_states].state = j;
4818             ++object->num_contained_tss_states;
4819         }
4820     }
4821     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){
4822         DWORD map = object->changed.samplerState[i];
4823
4824         for (j = 0; map; map >>= 1, ++j)
4825         {
4826             if (!(map & 1)) continue;
4827
4828             object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
4829             object->contained_sampler_states[object->num_contained_sampler_states].state = j;
4830             ++object->num_contained_sampler_states;
4831         }
4832     }
4833
4834     *ppStateBlock = (IWineD3DStateBlock*) object;
4835     This->isRecordingState = FALSE;
4836     This->updateStateBlock = This->stateBlock;
4837     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4838     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4839     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4840     return WINED3D_OK;
4841 }
4842
4843 /*****
4844  * Scene related functions
4845  *****/
4846 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4847     /* At the moment we have no need for any functionality at the beginning
4848        of a scene                                                          */
4849     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4850     TRACE("(%p)\n", This);
4851
4852     if(This->inScene) {
4853         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4854         return WINED3DERR_INVALIDCALL;
4855     }
4856     This->inScene = TRUE;
4857     return WINED3D_OK;
4858 }
4859
4860 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4861     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4862     TRACE("(%p)\n", This);
4863
4864     if(!This->inScene) {
4865         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4866         return WINED3DERR_INVALIDCALL;
4867     }
4868
4869     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4870     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4871     glFlush();
4872     /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4873      * fails
4874      */
4875
4876     This->inScene = FALSE;
4877     return WINED3D_OK;
4878 }
4879
4880 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4881                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4882                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4883     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4884     IWineD3DSwapChain *swapChain = NULL;
4885     int i;
4886     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4887
4888     TRACE("(%p) Presenting the frame\n", This);
4889
4890     for(i = 0 ; i < swapchains ; i ++) {
4891
4892         IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain);
4893         TRACE("presentinng chain %d, %p\n", i, swapChain);
4894         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4895         IWineD3DSwapChain_Release(swapChain);
4896     }
4897
4898     return WINED3D_OK;
4899 }
4900
4901 /* Not called from the VTable (internal subroutine) */
4902 HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfaceImpl *target, DWORD Count,
4903                                         CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
4904                                         float Z, DWORD Stencil) {
4905     GLbitfield     glMask = 0;
4906     unsigned int   i;
4907     WINED3DRECT curRect;
4908     RECT vp_rect;
4909     const WINED3DVIEWPORT *vp = &This->stateBlock->viewport;
4910     UINT drawable_width, drawable_height;
4911     IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget;
4912     IWineD3DSwapChainImpl *swapchain = NULL;
4913
4914     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4915      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4916      * for the cleared parts, and the untouched parts.
4917      *
4918      * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4919      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4920      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4921      * checking all this if the dest surface is in the drawable anyway.
4922      */
4923     if((Flags & WINED3DCLEAR_TARGET) && !(target->Flags & SFLAG_INDRAWABLE)) {
4924         while(1) {
4925             if(vp->X != 0 || vp->Y != 0 ||
4926                vp->Width < target->currentDesc.Width || vp->Height < target->currentDesc.Height) {
4927                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4928                 break;
4929             }
4930             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4931                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4932                This->stateBlock->scissorRect.right < target->currentDesc.Width ||
4933                This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) {
4934                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4935                 break;
4936             }
4937             if(Count > 0 && pRects && (
4938                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4939                pRects[0].x2 < target->currentDesc.Width ||
4940                pRects[0].y2 < target->currentDesc.Height)) {
4941                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4942                 break;
4943             }
4944             break;
4945         }
4946     }
4947
4948     target->get_drawable_size(target, &drawable_width, &drawable_height);
4949
4950     ActivateContext(This, (IWineD3DSurface *) target, CTXUSAGE_CLEAR);
4951     ENTER_GL();
4952
4953     /* Only set the values up once, as they are not changing */
4954     if (Flags & WINED3DCLEAR_STENCIL) {
4955         glClearStencil(Stencil);
4956         checkGLcall("glClearStencil");
4957         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4958         glStencilMask(0xFFFFFFFF);
4959     }
4960
4961     if (Flags & WINED3DCLEAR_ZBUFFER) {
4962         DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
4963         glDepthMask(GL_TRUE);
4964         glClearDepth(Z);
4965         checkGLcall("glClearDepth");
4966         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4967         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4968
4969         if (vp->X != 0 || vp->Y != 0 ||
4970                 vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) {
4971             surface_load_ds_location(This->stencilBufferTarget, location);
4972         }
4973         else if (This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4974                 This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4975                 This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width ||
4976                 This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) {
4977             surface_load_ds_location(This->stencilBufferTarget, location);
4978         }
4979         else if (Count > 0 && pRects && (
4980                 pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4981                 pRects[0].x2 < depth_stencil->currentDesc.Width ||
4982                 pRects[0].y2 < depth_stencil->currentDesc.Height)) {
4983             surface_load_ds_location(This->stencilBufferTarget, location);
4984         }
4985     }
4986
4987     if (Flags & WINED3DCLEAR_TARGET) {
4988         TRACE("Clearing screen with glClear to color %x\n", Color);
4989         glClearColor(D3DCOLOR_R(Color),
4990                      D3DCOLOR_G(Color),
4991                      D3DCOLOR_B(Color),
4992                      D3DCOLOR_A(Color));
4993         checkGLcall("glClearColor");
4994
4995         /* Clear ALL colors! */
4996         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4997         glMask = glMask | GL_COLOR_BUFFER_BIT;
4998     }
4999
5000     vp_rect.left = vp->X;
5001     vp_rect.top = vp->Y;
5002     vp_rect.right = vp->X + vp->Width;
5003     vp_rect.bottom = vp->Y + vp->Height;
5004     if (!(Count > 0 && pRects)) {
5005         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5006             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
5007         }
5008         if(This->render_offscreen) {
5009             glScissor(vp_rect.left, vp_rect.top,
5010                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
5011         } else {
5012             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
5013                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
5014         }
5015         checkGLcall("glScissor");
5016         glClear(glMask);
5017         checkGLcall("glClear");
5018     } else {
5019         /* Now process each rect in turn */
5020         for (i = 0; i < Count; i++) {
5021             /* Note gl uses lower left, width/height */
5022             IntersectRect((RECT *)&curRect, &vp_rect, (const RECT *)&pRects[i]);
5023             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5024                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
5025             }
5026             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
5027                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
5028                   curRect.x1, (target->currentDesc.Height - curRect.y2),
5029                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5030
5031             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
5032              * The rectangle is not cleared, no error is returned, but further rectanlges are
5033              * still cleared if they are valid
5034              */
5035             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
5036                 TRACE("Rectangle with negative dimensions, ignoring\n");
5037                 continue;
5038             }
5039
5040             if(This->render_offscreen) {
5041                 glScissor(curRect.x1, curRect.y1,
5042                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5043             } else {
5044                 glScissor(curRect.x1, drawable_height - curRect.y2,
5045                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5046             }
5047             checkGLcall("glScissor");
5048
5049             glClear(glMask);
5050             checkGLcall("glClear");
5051         }
5052     }
5053
5054     /* Restore the old values (why..?) */
5055     if (Flags & WINED3DCLEAR_STENCIL) {
5056         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5057     }
5058     if (Flags & WINED3DCLEAR_TARGET) {
5059         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
5060         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5061                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5062                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
5063                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5064
5065         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
5066          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
5067          */
5068         IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE);
5069     }
5070     if (Flags & WINED3DCLEAR_ZBUFFER) {
5071         /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
5072         DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
5073         surface_modify_ds_location(This->stencilBufferTarget, location);
5074     }
5075
5076     LEAVE_GL();
5077
5078     if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)target, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
5079         if (target == (IWineD3DSurfaceImpl*) swapchain->frontBuffer) {
5080             glFlush();
5081         }
5082         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5083     }
5084
5085     return WINED3D_OK;
5086 }
5087
5088 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
5089                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
5090     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5091     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
5092
5093     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
5094           Count, pRects, Flags, Color, Z, Stencil);
5095
5096     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
5097         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
5098         /* TODO: What about depth stencil buffers without stencil bits? */
5099         return WINED3DERR_INVALIDCALL;
5100     }
5101
5102     return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil);
5103 }
5104
5105 /*****
5106  * Drawing functions
5107  *****/
5108
5109 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
5110         WINED3DPRIMITIVETYPE primitive_type)
5111 {
5112     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5113
5114     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
5115
5116     This->updateStateBlock->changed.primitive_type = TRUE;
5117     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
5118 }
5119
5120 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
5121         WINED3DPRIMITIVETYPE *primitive_type)
5122 {
5123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5124
5125     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
5126
5127     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
5128
5129     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
5130 }
5131
5132 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
5133 {
5134     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5135
5136     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
5137
5138     if(!This->stateBlock->vertexDecl) {
5139         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5140         return WINED3DERR_INVALIDCALL;
5141     }
5142
5143     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
5144     if(This->stateBlock->streamIsUP) {
5145         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5146         This->stateBlock->streamIsUP = FALSE;
5147     }
5148
5149     if(This->stateBlock->loadBaseVertexIndex != 0) {
5150         This->stateBlock->loadBaseVertexIndex = 0;
5151         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5152     }
5153     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
5154     drawPrimitive(iface, vertex_count, 0/* NumVertices */, StartVertex /* start_idx */,
5155                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5156     return WINED3D_OK;
5157 }
5158
5159 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5160         UINT minIndex, UINT NumVertices, UINT startIndex, UINT index_count)
5161 {
5162     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5163     UINT                 idxStride = 2;
5164     IWineD3DBuffer *pIB;
5165     GLuint vbo;
5166
5167     pIB = This->stateBlock->pIndexData;
5168     if (!pIB) {
5169         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5170          * without an index buffer set. (The first time at least...)
5171          * D3D8 simply dies, but I doubt it can do much harm to return
5172          * D3DERR_INVALIDCALL there as well. */
5173         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
5174         return WINED3DERR_INVALIDCALL;
5175     }
5176
5177     if(!This->stateBlock->vertexDecl) {
5178         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5179         return WINED3DERR_INVALIDCALL;
5180     }
5181
5182     if(This->stateBlock->streamIsUP) {
5183         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5184         This->stateBlock->streamIsUP = FALSE;
5185     }
5186     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
5187
5188     TRACE("(%p) : min %u, vertex count %u, startIdx %u, index count %u\n",
5189             This, minIndex, NumVertices, startIndex, index_count);
5190
5191     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
5192         idxStride = 2;
5193     } else {
5194         idxStride = 4;
5195     }
5196
5197     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
5198         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
5199         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5200     }
5201
5202     drawPrimitive(iface, index_count, NumVertices, startIndex, idxStride,
5203             vbo ? NULL : ((struct wined3d_buffer *) pIB)->resource.allocatedMemory, minIndex);
5204
5205     return WINED3D_OK;
5206 }
5207
5208 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
5209         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
5210 {
5211     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5212     IWineD3DBuffer *vb;
5213
5214     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
5215             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
5216
5217     if(!This->stateBlock->vertexDecl) {
5218         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5219         return WINED3DERR_INVALIDCALL;
5220     }
5221
5222     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5223     vb = This->stateBlock->streamSource[0];
5224     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
5225     if (vb) IWineD3DBuffer_Release(vb);
5226     This->stateBlock->streamOffset[0] = 0;
5227     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5228     This->stateBlock->streamIsUP = TRUE;
5229     This->stateBlock->loadBaseVertexIndex = 0;
5230
5231     /* TODO: Only mark dirty if drawing from a different UP address */
5232     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5233
5234     drawPrimitive(iface, vertex_count, 0 /* NumVertices */, 0 /* start_idx */,
5235             0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5236
5237     /* MSDN specifies stream zero settings must be set to NULL */
5238     This->stateBlock->streamStride[0] = 0;
5239     This->stateBlock->streamSource[0] = NULL;
5240
5241     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5242      * the new stream sources or use UP drawing again
5243      */
5244     return WINED3D_OK;
5245 }
5246
5247 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, UINT MinVertexIndex,
5248         UINT NumVertices, UINT index_count, const void *pIndexData, WINED3DFORMAT IndexDataFormat,
5249         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
5250 {
5251     int                 idxStride;
5252     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5253     IWineD3DBuffer *vb;
5254     IWineD3DBuffer *ib;
5255
5256     TRACE("(%p) : MinVtxIdx %u, NumVIdx %u, index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u\n",
5257             This, MinVertexIndex, NumVertices, index_count, pIndexData,
5258             IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5259
5260     if(!This->stateBlock->vertexDecl) {
5261         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5262         return WINED3DERR_INVALIDCALL;
5263     }
5264
5265     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
5266         idxStride = 2;
5267     } else {
5268         idxStride = 4;
5269     }
5270
5271     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5272     vb = This->stateBlock->streamSource[0];
5273     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
5274     if (vb) IWineD3DBuffer_Release(vb);
5275     This->stateBlock->streamIsUP = TRUE;
5276     This->stateBlock->streamOffset[0] = 0;
5277     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5278
5279     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5280     This->stateBlock->baseVertexIndex = 0;
5281     This->stateBlock->loadBaseVertexIndex = 0;
5282     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5283     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5284     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5285
5286     drawPrimitive(iface, index_count, NumVertices, 0 /* start_idx */,
5287             idxStride, pIndexData, MinVertexIndex);
5288
5289     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5290     This->stateBlock->streamSource[0] = NULL;
5291     This->stateBlock->streamStride[0] = 0;
5292     ib = This->stateBlock->pIndexData;
5293     if(ib) {
5294         IWineD3DBuffer_Release(ib);
5295         This->stateBlock->pIndexData = NULL;
5296     }
5297     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5298      * SetStreamSource to specify a vertex buffer
5299      */
5300
5301     return WINED3D_OK;
5302 }
5303
5304 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
5305         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
5306 {
5307     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5308
5309     /* Mark the state dirty until we have nicer tracking
5310      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5311      * that value.
5312      */
5313     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5314     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5315     This->stateBlock->baseVertexIndex = 0;
5316     This->up_strided = DrawPrimStrideData;
5317     drawPrimitive(iface, vertex_count, 0, 0, 0, NULL, 0);
5318     This->up_strided = NULL;
5319     return WINED3D_OK;
5320 }
5321
5322 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
5323         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
5324         UINT NumVertices, const void *pIndexData, WINED3DFORMAT IndexDataFormat)
5325 {
5326     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5327     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
5328
5329     /* Mark the state dirty until we have nicer tracking
5330      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5331      * that value.
5332      */
5333     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5334     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5335     This->stateBlock->streamIsUP = TRUE;
5336     This->stateBlock->baseVertexIndex = 0;
5337     This->up_strided = DrawPrimStrideData;
5338     drawPrimitive(iface, vertex_count, 0 /* numindices */, 0 /* start_idx */, idxSize, pIndexData, 0 /* minindex */);
5339     This->up_strided = NULL;
5340     return WINED3D_OK;
5341 }
5342
5343 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
5344     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5345      * not callable by the app directly no parameter validation checks are needed here.
5346      */
5347     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5348     WINED3DLOCKED_BOX src;
5349     WINED3DLOCKED_BOX dst;
5350     HRESULT hr;
5351     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
5352
5353     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5354      * dirtification to improve loading performance.
5355      */
5356     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
5357     if(FAILED(hr)) return hr;
5358     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
5359     if(FAILED(hr)) {
5360     IWineD3DVolume_UnlockBox(pSourceVolume);
5361             return hr;
5362     }
5363
5364     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
5365
5366     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
5367     if(FAILED(hr)) {
5368         IWineD3DVolume_UnlockBox(pSourceVolume);
5369     } else {
5370         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
5371     }
5372     return hr;
5373 }
5374
5375 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5376 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5377     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5378     HRESULT hr = WINED3D_OK;
5379     WINED3DRESOURCETYPE sourceType;
5380     WINED3DRESOURCETYPE destinationType;
5381     int i ,levels;
5382
5383     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5384
5385     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5386
5387     /* verify that the source and destination textures aren't NULL */
5388     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5389         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5390              This, pSourceTexture, pDestinationTexture);
5391         hr = WINED3DERR_INVALIDCALL;
5392     }
5393
5394     if (pSourceTexture == pDestinationTexture) {
5395         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5396              This, pSourceTexture, pDestinationTexture);
5397         hr = WINED3DERR_INVALIDCALL;
5398     }
5399     /* Verify that the source and destination textures are the same type */
5400     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5401     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5402
5403     if (sourceType != destinationType) {
5404         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5405              This);
5406         hr = WINED3DERR_INVALIDCALL;
5407     }
5408
5409     /* check that both textures have the identical numbers of levels  */
5410     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5411         WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5412         hr = WINED3DERR_INVALIDCALL;
5413     }
5414
5415     if (WINED3D_OK == hr) {
5416         IWineD3DBaseTextureImpl *pDestImpl = (IWineD3DBaseTextureImpl *) pDestinationTexture;
5417
5418         /* Make sure that the destination texture is loaded */
5419         pDestImpl->baseTexture.internal_preload(pDestinationTexture, SRGB_RGB);
5420
5421         /* Update every surface level of the texture */
5422         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5423
5424         switch (sourceType) {
5425         case WINED3DRTYPE_TEXTURE:
5426             {
5427                 IWineD3DSurface *srcSurface;
5428                 IWineD3DSurface *destSurface;
5429
5430                 for (i = 0 ; i < levels ; ++i) {
5431                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5432                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5433                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5434                     IWineD3DSurface_Release(srcSurface);
5435                     IWineD3DSurface_Release(destSurface);
5436                     if (WINED3D_OK != hr) {
5437                         WARN("(%p) : Call to update surface failed\n", This);
5438                         return hr;
5439                     }
5440                 }
5441             }
5442             break;
5443         case WINED3DRTYPE_CUBETEXTURE:
5444             {
5445                 IWineD3DSurface *srcSurface;
5446                 IWineD3DSurface *destSurface;
5447                 WINED3DCUBEMAP_FACES faceType;
5448
5449                 for (i = 0 ; i < levels ; ++i) {
5450                     /* Update each cube face */
5451                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5452                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5453                         if (WINED3D_OK != hr) {
5454                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5455                         } else {
5456                             TRACE("Got srcSurface %p\n", srcSurface);
5457                         }
5458                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5459                         if (WINED3D_OK != hr) {
5460                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5461                         } else {
5462                             TRACE("Got desrSurface %p\n", destSurface);
5463                         }
5464                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5465                         IWineD3DSurface_Release(srcSurface);
5466                         IWineD3DSurface_Release(destSurface);
5467                         if (WINED3D_OK != hr) {
5468                             WARN("(%p) : Call to update surface failed\n", This);
5469                             return hr;
5470                         }
5471                     }
5472                 }
5473             }
5474             break;
5475
5476         case WINED3DRTYPE_VOLUMETEXTURE:
5477             {
5478                 IWineD3DVolume  *srcVolume  = NULL;
5479                 IWineD3DVolume  *destVolume = NULL;
5480
5481                 for (i = 0 ; i < levels ; ++i) {
5482                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5483                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5484                     hr =  IWineD3DDeviceImpl_UpdateVolume(iface, srcVolume, destVolume);
5485                     IWineD3DVolume_Release(srcVolume);
5486                     IWineD3DVolume_Release(destVolume);
5487                     if (WINED3D_OK != hr) {
5488                         WARN("(%p) : Call to update volume failed\n", This);
5489                         return hr;
5490                     }
5491                 }
5492             }
5493             break;
5494
5495         default:
5496             FIXME("(%p) : Unsupported source and destination type\n", This);
5497             hr = WINED3DERR_INVALIDCALL;
5498         }
5499     }
5500
5501     return hr;
5502 }
5503
5504 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5505     IWineD3DSwapChain *swapChain;
5506     HRESULT hr;
5507     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5508     if(hr == WINED3D_OK) {
5509         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5510                 IWineD3DSwapChain_Release(swapChain);
5511     }
5512     return hr;
5513 }
5514
5515 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5516     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5517     IWineD3DBaseTextureImpl *texture;
5518     DWORD i;
5519
5520     TRACE("(%p) : %p\n", This, pNumPasses);
5521
5522     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5523         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) {
5524             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5525             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5526         }
5527         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) {
5528             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5529             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5530         }
5531
5532         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5533         if (!texture || texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5534
5535         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) {
5536             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5537             return E_FAIL;
5538         }
5539         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) {
5540             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5541             return E_FAIL;
5542         }
5543         if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE &&
5544            This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) {
5545             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5546             return E_FAIL;
5547         }
5548     }
5549
5550     /* return a sensible default */
5551     *pNumPasses = 1;
5552
5553     TRACE("returning D3D_OK\n");
5554     return WINED3D_OK;
5555 }
5556
5557 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5558 {
5559     int i;
5560
5561     for (i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5562             IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5563             if (texture && (texture->resource.format_desc->format == WINED3DFMT_P8
5564                     || texture->resource.format_desc->format == WINED3DFMT_A8P8))
5565             {
5566                 IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5567             }
5568         }
5569 }
5570
5571 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5572     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5573     int j;
5574     UINT NewSize;
5575     PALETTEENTRY **palettes;
5576
5577     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5578
5579     if (PaletteNumber >= MAX_PALETTES) {
5580         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5581         return WINED3DERR_INVALIDCALL;
5582     }
5583
5584     if (PaletteNumber >= This->NumberOfPalettes) {
5585         NewSize = This->NumberOfPalettes;
5586         do {
5587            NewSize *= 2;
5588         } while(PaletteNumber >= NewSize);
5589         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5590         if (!palettes) {
5591             ERR("Out of memory!\n");
5592             return E_OUTOFMEMORY;
5593         }
5594         This->palettes = palettes;
5595         This->NumberOfPalettes = NewSize;
5596     }
5597
5598     if (!This->palettes[PaletteNumber]) {
5599         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5600         if (!This->palettes[PaletteNumber]) {
5601             ERR("Out of memory!\n");
5602             return E_OUTOFMEMORY;
5603         }
5604     }
5605
5606     for (j = 0; j < 256; ++j) {
5607         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5608         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5609         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5610         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5611     }
5612     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5613     TRACE("(%p) : returning\n", This);
5614     return WINED3D_OK;
5615 }
5616
5617 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5618     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5619     int j;
5620     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5621     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5622         /* What happens in such situation isn't documented; Native seems to silently abort
5623            on such conditions. Return Invalid Call. */
5624         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5625         return WINED3DERR_INVALIDCALL;
5626     }
5627     for (j = 0; j < 256; ++j) {
5628         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5629         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5630         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5631         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5632     }
5633     TRACE("(%p) : returning\n", This);
5634     return WINED3D_OK;
5635 }
5636
5637 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5638     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5639     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5640     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5641        (tested with reference rasterizer). Return Invalid Call. */
5642     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5643         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5644         return WINED3DERR_INVALIDCALL;
5645     }
5646     /*TODO: stateblocks */
5647     if (This->currentPalette != PaletteNumber) {
5648         This->currentPalette = PaletteNumber;
5649         dirtify_p8_texture_samplers(This);
5650     }
5651     TRACE("(%p) : returning\n", This);
5652     return WINED3D_OK;
5653 }
5654
5655 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5657     if (PaletteNumber == NULL) {
5658         WARN("(%p) : returning Invalid Call\n", This);
5659         return WINED3DERR_INVALIDCALL;
5660     }
5661     /*TODO: stateblocks */
5662     *PaletteNumber = This->currentPalette;
5663     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5664     return WINED3D_OK;
5665 }
5666
5667 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5668     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5669     static BOOL warned;
5670     if (!warned)
5671     {
5672         FIXME("(%p) : stub\n", This);
5673         warned = TRUE;
5674     }
5675
5676     This->softwareVertexProcessing = bSoftware;
5677     return WINED3D_OK;
5678 }
5679
5680
5681 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5682     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5683     static BOOL warned;
5684     if (!warned)
5685     {
5686         FIXME("(%p) : stub\n", This);
5687         warned = TRUE;
5688     }
5689     return This->softwareVertexProcessing;
5690 }
5691
5692
5693 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5695     IWineD3DSwapChain *swapChain;
5696     HRESULT hr;
5697
5698     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5699
5700     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5701     if(hr == WINED3D_OK){
5702         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5703         IWineD3DSwapChain_Release(swapChain);
5704     }else{
5705         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5706     }
5707     return hr;
5708 }
5709
5710
5711 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5712     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5713     static BOOL warned;
5714     if(nSegments != 0.0f) {
5715         if (!warned)
5716         {
5717             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5718             warned = TRUE;
5719         }
5720     }
5721     return WINED3D_OK;
5722 }
5723
5724 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5725     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5726     static BOOL warned;
5727     if (!warned)
5728     {
5729         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5730         warned = TRUE;
5731     }
5732     return 0.0f;
5733 }
5734
5735 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5736     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5737     /** TODO: remove casts to IWineD3DSurfaceImpl
5738      *       NOTE: move code to surface to accomplish this
5739       ****************************************/
5740     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5741     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)pDestinationSurface;
5742     int srcWidth, srcHeight;
5743     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5744     WINED3DFORMAT destFormat, srcFormat;
5745     UINT          destSize;
5746     int srcLeft, destLeft, destTop;
5747     WINED3DPOOL       srcPool, destPool;
5748     int offset    = 0;
5749     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5750     const struct GlPixelFormatDesc *src_format_desc, *dst_format_desc;
5751     GLenum dummy;
5752     int sampler;
5753     int bpp;
5754     CONVERT_TYPES convert = NO_CONVERSION;
5755
5756     WINED3DSURFACE_DESC  winedesc;
5757
5758     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5759
5760     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5761     srcSurfaceWidth = winedesc.width;
5762     srcSurfaceHeight = winedesc.height;
5763     srcPool = winedesc.pool;
5764     srcFormat = winedesc.format;
5765
5766     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5767     destSurfaceWidth = winedesc.width;
5768     destSurfaceHeight = winedesc.height;
5769     destPool = winedesc.pool;
5770     destFormat = winedesc.format;
5771     destSize = winedesc.size;
5772
5773     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5774         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5775         return WINED3DERR_INVALIDCALL;
5776     }
5777
5778     /* This call loads the opengl surface directly, instead of copying the surface to the
5779      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5780      * copy in sysmem and use regular surface loading.
5781      */
5782     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5783     if(convert != NO_CONVERSION) {
5784         return IWineD3DSurface_BltFast(pDestinationSurface,
5785                                         pDestPoint  ? pDestPoint->x : 0,
5786                                         pDestPoint  ? pDestPoint->y : 0,
5787                                         pSourceSurface, pSourceRect, 0);
5788     }
5789
5790     if (destFormat == WINED3DFMT_UNKNOWN) {
5791         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5792         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5793
5794         /* Get the update surface description */
5795         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5796     }
5797
5798     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5799
5800     ENTER_GL();
5801     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5802     checkGLcall("glActiveTextureARB");
5803     LEAVE_GL();
5804
5805     /* Make sure the surface is loaded and up to date */
5806     surface_internal_preload(pDestinationSurface, SRGB_RGB);
5807     IWineD3DSurface_BindTexture(pDestinationSurface, FALSE);
5808
5809     src_format_desc = ((IWineD3DSurfaceImpl *)pSrcSurface)->resource.format_desc;
5810     dst_format_desc = dst_impl->resource.format_desc;
5811
5812     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5813     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5814     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5815     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5816     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5817     destTop    = pDestPoint  ? pDestPoint->y : 0;
5818
5819
5820     /* This function doesn't support compressed textures
5821     the pitch is just bytesPerPixel * width */
5822     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5823         rowoffset = srcSurfaceWidth * src_format_desc->byte_count;
5824         offset   += srcLeft * src_format_desc->byte_count;
5825         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5826     }
5827     /* TODO DXT formats */
5828
5829     if(pSourceRect != NULL && pSourceRect->top != 0){
5830        offset +=  pSourceRect->top * srcSurfaceWidth * src_format_desc->byte_count;
5831     }
5832     TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n",
5833             This, dst_impl->texture_level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat,
5834             dst_format_desc->glType, IWineD3DSurface_GetData(pSourceSurface), offset);
5835
5836     /* Sanity check */
5837     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5838
5839         /* need to lock the surface to get the data */
5840         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5841     }
5842
5843     ENTER_GL();
5844
5845     /* TODO: Cube and volume support */
5846     if(rowoffset != 0){
5847         /* not a whole row so we have to do it a line at a time */
5848         int j;
5849
5850         /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5851         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5852
5853         for (j = destTop; j < (srcHeight + destTop); ++j)
5854         {
5855             glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, j,
5856                     srcWidth, 1, dst_format_desc->glFormat, dst_format_desc->glType,data);
5857             data += rowoffset;
5858         }
5859
5860     } else { /* Full width, so just write out the whole texture */
5861         const unsigned char* data = ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5862
5863         if (dst_format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
5864         {
5865             if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth)
5866             {
5867                 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */
5868                 FIXME("Updating part of a compressed texture is not supported.\n");
5869             }
5870             if (destFormat != srcFormat)
5871             {
5872                 FIXME("Updating mixed format compressed textures is not supported.\n");
5873             }
5874             else
5875             {
5876                 GL_EXTCALL(glCompressedTexImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5877                         dst_format_desc->glInternal, srcWidth, srcHeight, 0, destSize, data));
5878             }
5879         }
5880         else
5881         {
5882             glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, destTop,
5883                     srcWidth, srcHeight, dst_format_desc->glFormat, dst_format_desc->glType, data);
5884         }
5885      }
5886     checkGLcall("glTexSubImage2D");
5887
5888     LEAVE_GL();
5889
5890     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5891     sampler = This->rev_tex_unit_map[0];
5892     if (sampler != -1) {
5893         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5894     }
5895
5896     return WINED3D_OK;
5897 }
5898
5899 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5900     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5901     struct WineD3DRectPatch *patch;
5902     GLenum old_primitive_type;
5903     unsigned int i;
5904     struct list *e;
5905     BOOL found;
5906     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5907
5908     if(!(Handle || pRectPatchInfo)) {
5909         /* TODO: Write a test for the return value, thus the FIXME */
5910         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5911         return WINED3DERR_INVALIDCALL;
5912     }
5913
5914     if(Handle) {
5915         i = PATCHMAP_HASHFUNC(Handle);
5916         found = FALSE;
5917         LIST_FOR_EACH(e, &This->patches[i]) {
5918             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5919             if(patch->Handle == Handle) {
5920                 found = TRUE;
5921                 break;
5922             }
5923         }
5924
5925         if(!found) {
5926             TRACE("Patch does not exist. Creating a new one\n");
5927             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5928             patch->Handle = Handle;
5929             list_add_head(&This->patches[i], &patch->entry);
5930         } else {
5931             TRACE("Found existing patch %p\n", patch);
5932         }
5933     } else {
5934         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5935          * attributes we have to tesselate, read back, and draw. This needs a patch
5936          * management structure instance. Create one.
5937          *
5938          * A possible improvement is to check if a vertex shader is used, and if not directly
5939          * draw the patch.
5940          */
5941         FIXME("Drawing an uncached patch. This is slow\n");
5942         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5943     }
5944
5945     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5946        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5947        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5948         HRESULT hr;
5949         TRACE("Tesselation density or patch info changed, retesselating\n");
5950
5951         if(pRectPatchInfo) {
5952             patch->RectPatchInfo = *pRectPatchInfo;
5953         }
5954         patch->numSegs[0] = pNumSegs[0];
5955         patch->numSegs[1] = pNumSegs[1];
5956         patch->numSegs[2] = pNumSegs[2];
5957         patch->numSegs[3] = pNumSegs[3];
5958
5959         hr = tesselate_rectpatch(This, patch);
5960         if(FAILED(hr)) {
5961             WARN("Patch tesselation failed\n");
5962
5963             /* Do not release the handle to store the params of the patch */
5964             if(!Handle) {
5965                 HeapFree(GetProcessHeap(), 0, patch);
5966             }
5967             return hr;
5968         }
5969     }
5970
5971     This->currentPatch = patch;
5972     old_primitive_type = This->stateBlock->gl_primitive_type;
5973     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5974     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5975     This->stateBlock->gl_primitive_type = old_primitive_type;
5976     This->currentPatch = NULL;
5977
5978     /* Destroy uncached patches */
5979     if(!Handle) {
5980         HeapFree(GetProcessHeap(), 0, patch->mem);
5981         HeapFree(GetProcessHeap(), 0, patch);
5982     }
5983     return WINED3D_OK;
5984 }
5985
5986 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5987     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5988     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5989     FIXME("(%p) : Stub\n", This);
5990     return WINED3D_OK;
5991 }
5992
5993 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5994     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5995     int i;
5996     struct WineD3DRectPatch *patch;
5997     struct list *e;
5998     TRACE("(%p) Handle(%d)\n", This, Handle);
5999
6000     i = PATCHMAP_HASHFUNC(Handle);
6001     LIST_FOR_EACH(e, &This->patches[i]) {
6002         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
6003         if(patch->Handle == Handle) {
6004             TRACE("Deleting patch %p\n", patch);
6005             list_remove(&patch->entry);
6006             HeapFree(GetProcessHeap(), 0, patch->mem);
6007             HeapFree(GetProcessHeap(), 0, patch);
6008             return WINED3D_OK;
6009         }
6010     }
6011
6012     /* TODO: Write a test for the return value */
6013     FIXME("Attempt to destroy nonexistent patch\n");
6014     return WINED3DERR_INVALIDCALL;
6015 }
6016
6017 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
6018     HRESULT hr;
6019     IWineD3DSwapChain *swapchain;
6020
6021     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
6022     if (SUCCEEDED(hr)) {
6023         IWineD3DSwapChain_Release((IUnknown *)swapchain);
6024         return swapchain;
6025     }
6026
6027     return NULL;
6028 }
6029
6030 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface,
6031         const WINED3DRECT *rect, const float color[4])
6032 {
6033     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6034     IWineD3DSwapChain *swapchain;
6035
6036     swapchain = get_swapchain(surface);
6037     if (swapchain) {
6038         GLenum buffer;
6039
6040         TRACE("Surface %p is onscreen\n", surface);
6041
6042         ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD);
6043         ENTER_GL();
6044         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6045         buffer = surface_get_gl_buffer(surface, swapchain);
6046         glDrawBuffer(buffer);
6047         checkGLcall("glDrawBuffer()");
6048     } else {
6049         TRACE("Surface %p is offscreen\n", surface);
6050
6051         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6052         ENTER_GL();
6053         context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo);
6054         context_attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
6055         context_attach_depth_stencil_fbo(This, GL_FRAMEBUFFER_EXT, NULL, FALSE);
6056     }
6057
6058     if (rect) {
6059         glEnable(GL_SCISSOR_TEST);
6060         if(!swapchain) {
6061             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
6062         } else {
6063             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
6064                     rect->x2 - rect->x1, rect->y2 - rect->y1);
6065         }
6066         checkGLcall("glScissor");
6067         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
6068     } else {
6069         glDisable(GL_SCISSOR_TEST);
6070     }
6071     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6072
6073     glDisable(GL_BLEND);
6074     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE));
6075
6076     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6077     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
6078
6079     glClearColor(color[0], color[1], color[2], color[3]);
6080     glClear(GL_COLOR_BUFFER_BIT);
6081     checkGLcall("glClear");
6082
6083     if (This->activeContext->current_fbo) {
6084         context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->current_fbo->id);
6085     } else {
6086         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6087         checkGLcall("glBindFramebuffer()");
6088     }
6089
6090     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
6091             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
6092         glDrawBuffer(GL_BACK);
6093         checkGLcall("glDrawBuffer()");
6094     }
6095
6096     LEAVE_GL();
6097 }
6098
6099 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
6100     unsigned int r, g, b, a;
6101     DWORD ret;
6102
6103     if(destfmt == WINED3DFMT_A8R8G8B8 || destfmt == WINED3DFMT_X8R8G8B8 ||
6104        destfmt == WINED3DFMT_R8G8B8)
6105         return color;
6106
6107     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
6108
6109     a = (color & 0xff000000) >> 24;
6110     r = (color & 0x00ff0000) >> 16;
6111     g = (color & 0x0000ff00) >>  8;
6112     b = (color & 0x000000ff) >>  0;
6113
6114     switch(destfmt)
6115     {
6116         case WINED3DFMT_R5G6B5:
6117             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
6118             r = (r * 32) / 256;
6119             g = (g * 64) / 256;
6120             b = (b * 32) / 256;
6121             ret  = r << 11;
6122             ret |= g << 5;
6123             ret |= b;
6124             TRACE("Returning %08x\n", ret);
6125             return ret;
6126
6127         case WINED3DFMT_X1R5G5B5:
6128         case WINED3DFMT_A1R5G5B5:
6129             a = (a *  2) / 256;
6130             r = (r * 32) / 256;
6131             g = (g * 32) / 256;
6132             b = (b * 32) / 256;
6133             ret  = a << 15;
6134             ret |= r << 10;
6135             ret |= g <<  5;
6136             ret |= b <<  0;
6137             TRACE("Returning %08x\n", ret);
6138             return ret;
6139
6140         case WINED3DFMT_A8_UNORM:
6141             TRACE("Returning %08x\n", a);
6142             return a;
6143
6144         case WINED3DFMT_X4R4G4B4:
6145         case WINED3DFMT_A4R4G4B4:
6146             a = (a * 16) / 256;
6147             r = (r * 16) / 256;
6148             g = (g * 16) / 256;
6149             b = (b * 16) / 256;
6150             ret  = a << 12;
6151             ret |= r <<  8;
6152             ret |= g <<  4;
6153             ret |= b <<  0;
6154             TRACE("Returning %08x\n", ret);
6155             return ret;
6156
6157         case WINED3DFMT_R3G3B2:
6158             r = (r * 8) / 256;
6159             g = (g * 8) / 256;
6160             b = (b * 4) / 256;
6161             ret  = r <<  5;
6162             ret |= g <<  2;
6163             ret |= b <<  0;
6164             TRACE("Returning %08x\n", ret);
6165             return ret;
6166
6167         case WINED3DFMT_X8B8G8R8:
6168         case WINED3DFMT_R8G8B8A8_UNORM:
6169             ret  = a << 24;
6170             ret |= b << 16;
6171             ret |= g <<  8;
6172             ret |= r <<  0;
6173             TRACE("Returning %08x\n", ret);
6174             return ret;
6175
6176         case WINED3DFMT_A2R10G10B10:
6177             a = (a *    4) / 256;
6178             r = (r * 1024) / 256;
6179             g = (g * 1024) / 256;
6180             b = (b * 1024) / 256;
6181             ret  = a << 30;
6182             ret |= r << 20;
6183             ret |= g << 10;
6184             ret |= b <<  0;
6185             TRACE("Returning %08x\n", ret);
6186             return ret;
6187
6188         case WINED3DFMT_R10G10B10A2_UNORM:
6189             a = (a *    4) / 256;
6190             r = (r * 1024) / 256;
6191             g = (g * 1024) / 256;
6192             b = (b * 1024) / 256;
6193             ret  = a << 30;
6194             ret |= b << 20;
6195             ret |= g << 10;
6196             ret |= r <<  0;
6197             TRACE("Returning %08x\n", ret);
6198             return ret;
6199
6200         default:
6201             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
6202             return 0;
6203     }
6204 }
6205
6206 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6207     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6208     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6209     WINEDDBLTFX BltFx;
6210     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
6211
6212     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6213         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6214         return WINED3DERR_INVALIDCALL;
6215     }
6216
6217     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6218         const float c[4] = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)};
6219         color_fill_fbo(iface, pSurface, pRect, c);
6220         return WINED3D_OK;
6221     } else {
6222         /* Just forward this to the DirectDraw blitting engine */
6223         memset(&BltFx, 0, sizeof(BltFx));
6224         BltFx.dwSize = sizeof(BltFx);
6225         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format_desc->format);
6226         return IWineD3DSurface_Blt(pSurface, (const RECT *)pRect, NULL, NULL,
6227                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
6228     }
6229 }
6230
6231 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
6232         IWineD3DRendertargetView *rendertarget_view, const float color[4])
6233 {
6234     IWineD3DResource *resource;
6235     IWineD3DSurface *surface;
6236     HRESULT hr;
6237
6238     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
6239     if (FAILED(hr))
6240     {
6241         ERR("Failed to get resource, hr %#x\n", hr);
6242         return;
6243     }
6244
6245     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
6246     {
6247         FIXME("Only supported on surface resources\n");
6248         IWineD3DResource_Release(resource);
6249         return;
6250     }
6251
6252     surface = (IWineD3DSurface *)resource;
6253
6254     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
6255     {
6256         color_fill_fbo(iface, surface, NULL, color);
6257     }
6258     else
6259     {
6260         WINEDDBLTFX BltFx;
6261         WINED3DCOLOR c;
6262
6263         WARN("Converting to WINED3DCOLOR, this might give incorrect results\n");
6264
6265         c = ((DWORD)(color[2] * 255.0f));
6266         c |= ((DWORD)(color[1] * 255.0f)) << 8;
6267         c |= ((DWORD)(color[0] * 255.0f)) << 16;
6268         c |= ((DWORD)(color[3] * 255.0f)) << 24;
6269
6270         /* Just forward this to the DirectDraw blitting engine */
6271         memset(&BltFx, 0, sizeof(BltFx));
6272         BltFx.dwSize = sizeof(BltFx);
6273         BltFx.u5.dwFillColor = argb_to_fmt(c, ((IWineD3DSurfaceImpl *)surface)->resource.format_desc->format);
6274         hr = IWineD3DSurface_Blt(surface, NULL, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
6275         if (FAILED(hr))
6276         {
6277             ERR("Blt failed, hr %#x\n", hr);
6278         }
6279     }
6280
6281     IWineD3DResource_Release(resource);
6282 }
6283
6284 /* rendertarget and depth stencil functions */
6285 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6286     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6287
6288     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6289         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
6290         return WINED3DERR_INVALIDCALL;
6291     }
6292
6293     *ppRenderTarget = This->render_targets[RenderTargetIndex];
6294     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6295     /* Note inc ref on returned surface */
6296     if(*ppRenderTarget != NULL)
6297         IWineD3DSurface_AddRef(*ppRenderTarget);
6298     return WINED3D_OK;
6299 }
6300
6301 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6302     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6303     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6304     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6305     IWineD3DSwapChainImpl *Swapchain;
6306     HRESULT hr;
6307
6308     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6309
6310     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6311     if(hr != WINED3D_OK) {
6312         ERR("Can't get the swapchain\n");
6313         return hr;
6314     }
6315
6316     /* Make sure to release the swapchain */
6317     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6318
6319     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6320         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6321         return WINED3DERR_INVALIDCALL;
6322     }
6323     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6324         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6325         return WINED3DERR_INVALIDCALL;
6326     }
6327
6328     if(Swapchain->frontBuffer != Front) {
6329         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6330
6331         if(Swapchain->frontBuffer)
6332         {
6333             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6334             ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags &= ~SFLAG_SWAPCHAIN;
6335         }
6336         Swapchain->frontBuffer = Front;
6337
6338         if(Swapchain->frontBuffer) {
6339             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6340             ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags |= SFLAG_SWAPCHAIN;
6341         }
6342     }
6343
6344     if(Back && !Swapchain->backBuffer) {
6345         /* We need memory for the back buffer array - only one back buffer this way */
6346         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6347         if(!Swapchain->backBuffer) {
6348             ERR("Out of memory\n");
6349             return E_OUTOFMEMORY;
6350         }
6351     }
6352
6353     if(Swapchain->backBuffer[0] != Back) {
6354         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6355
6356         /* What to do about the context here in the case of multithreading? Not sure.
6357          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6358          */
6359         WARN("No active context?\n");
6360
6361         ENTER_GL();
6362         if(!Swapchain->backBuffer[0]) {
6363             /* GL was told to draw to the front buffer at creation,
6364              * undo that
6365              */
6366             glDrawBuffer(GL_BACK);
6367             checkGLcall("glDrawBuffer(GL_BACK)");
6368             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6369             Swapchain->presentParms.BackBufferCount = 1;
6370         } else if (!Back) {
6371             /* That makes problems - disable for now */
6372             /* glDrawBuffer(GL_FRONT); */
6373             checkGLcall("glDrawBuffer(GL_FRONT)");
6374             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6375             Swapchain->presentParms.BackBufferCount = 0;
6376         }
6377         LEAVE_GL();
6378
6379         if(Swapchain->backBuffer[0])
6380         {
6381             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6382             ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags &= ~SFLAG_SWAPCHAIN;
6383         }
6384         Swapchain->backBuffer[0] = Back;
6385
6386         if(Swapchain->backBuffer[0]) {
6387             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6388             ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags |= SFLAG_SWAPCHAIN;
6389         } else {
6390             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6391             Swapchain->backBuffer = NULL;
6392         }
6393
6394     }
6395
6396     return WINED3D_OK;
6397 }
6398
6399 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6400     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6401     *ppZStencilSurface = This->stencilBufferTarget;
6402     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6403
6404     if(*ppZStencilSurface != NULL) {
6405         /* Note inc ref on returned surface */
6406         IWineD3DSurface_AddRef(*ppZStencilSurface);
6407         return WINED3D_OK;
6408     } else {
6409         return WINED3DERR_NOTFOUND;
6410     }
6411 }
6412
6413 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6414         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip)
6415 {
6416     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6417     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6418     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6419     GLenum gl_filter;
6420     POINT offset = {0, 0};
6421
6422     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6423             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6424     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6425     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6426
6427     switch (filter) {
6428         case WINED3DTEXF_LINEAR:
6429             gl_filter = GL_LINEAR;
6430             break;
6431
6432         default:
6433             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6434         case WINED3DTEXF_NONE:
6435         case WINED3DTEXF_POINT:
6436             gl_filter = GL_NEAREST;
6437             break;
6438     }
6439
6440     /* Attach src surface to src fbo */
6441     src_swapchain = get_swapchain(src_surface);
6442     dst_swapchain = get_swapchain(dst_surface);
6443
6444     if (src_swapchain) ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6445     else if (dst_swapchain) ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6446     else ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6447
6448     if (src_swapchain) {
6449         GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6450
6451         TRACE("Source surface %p is onscreen\n", src_surface);
6452         /* Make sure the drawable is up to date. In the offscreen case
6453          * attach_surface_fbo() implicitly takes care of this. */
6454         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
6455
6456         if(buffer == GL_FRONT) {
6457             RECT windowsize;
6458             UINT h;
6459             ClientToScreen(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &offset);
6460             GetClientRect(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &windowsize);
6461             h = windowsize.bottom - windowsize.top;
6462             src_rect->x1 -= offset.x; src_rect->x2 -=offset.x;
6463             src_rect->y1 =  offset.y + h - src_rect->y1;
6464             src_rect->y2 =  offset.y + h - src_rect->y2;
6465         } else {
6466             src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6467             src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6468         }
6469
6470         ENTER_GL();
6471         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
6472         glReadBuffer(buffer);
6473         checkGLcall("glReadBuffer()");
6474     } else {
6475         TRACE("Source surface %p is offscreen\n", src_surface);
6476         ENTER_GL();
6477         context_bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->activeContext->src_fbo);
6478         context_attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
6479         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
6480         checkGLcall("glReadBuffer()");
6481         context_attach_depth_stencil_fbo(This, GL_READ_FRAMEBUFFER_EXT, NULL, FALSE);
6482     }
6483     LEAVE_GL();
6484
6485     /* Attach dst surface to dst fbo */
6486     if (dst_swapchain) {
6487         GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6488
6489         TRACE("Destination surface %p is onscreen\n", dst_surface);
6490         /* Make sure the drawable is up to date. In the offscreen case
6491          * attach_surface_fbo() implicitly takes care of this. */
6492         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
6493
6494         if(buffer == GL_FRONT) {
6495             RECT windowsize;
6496             UINT h;
6497             ClientToScreen(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &offset);
6498             GetClientRect(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &windowsize);
6499             h = windowsize.bottom - windowsize.top;
6500             dst_rect->x1 -= offset.x; dst_rect->x2 -=offset.x;
6501             dst_rect->y1 =  offset.y + h - dst_rect->y1;
6502             dst_rect->y2 =  offset.y + h - dst_rect->y2;
6503         } else {
6504             /* Screen coords = window coords, surface height = window height */
6505             dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6506             dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6507         }
6508
6509         ENTER_GL();
6510         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
6511         glDrawBuffer(buffer);
6512         checkGLcall("glDrawBuffer()");
6513     } else {
6514         TRACE("Destination surface %p is offscreen\n", dst_surface);
6515
6516         ENTER_GL();
6517         context_bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->activeContext->dst_fbo);
6518         context_attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
6519         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
6520         checkGLcall("glDrawBuffer()");
6521         context_attach_depth_stencil_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, NULL, FALSE);
6522     }
6523     glDisable(GL_SCISSOR_TEST);
6524     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6525
6526     if (flip) {
6527         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6528                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
6529         checkGLcall("glBlitFramebuffer()");
6530     } else {
6531         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6532                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
6533         checkGLcall("glBlitFramebuffer()");
6534     }
6535
6536     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
6537
6538     if (This->activeContext->current_fbo) {
6539         context_bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->activeContext->current_fbo->id);
6540     } else {
6541         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6542         checkGLcall("glBindFramebuffer()");
6543     }
6544
6545     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6546     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6547             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6548         glDrawBuffer(GL_BACK);
6549         checkGLcall("glDrawBuffer()");
6550     }
6551     LEAVE_GL();
6552 }
6553
6554 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6555     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6556     WINED3DVIEWPORT viewport;
6557
6558     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6559
6560     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6561         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6562              This, RenderTargetIndex, GL_LIMITS(buffers));
6563         return WINED3DERR_INVALIDCALL;
6564     }
6565
6566     /* MSDN says that null disables the render target
6567     but a device must always be associated with a render target
6568     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6569     */
6570     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6571         FIXME("Trying to set render target 0 to NULL\n");
6572         return WINED3DERR_INVALIDCALL;
6573     }
6574     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6575         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);
6576         return WINED3DERR_INVALIDCALL;
6577     }
6578
6579     /* If we are trying to set what we already have, don't bother */
6580     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6581         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6582         return WINED3D_OK;
6583     }
6584     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6585     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6586     This->render_targets[RenderTargetIndex] = pRenderTarget;
6587
6588     /* Render target 0 is special */
6589     if(RenderTargetIndex == 0) {
6590         /* Finally, reset the viewport as the MSDN states. */
6591         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6592         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6593         viewport.X      = 0;
6594         viewport.Y      = 0;
6595         viewport.MaxZ   = 1.0f;
6596         viewport.MinZ   = 0.0f;
6597         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6598         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6599          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6600          */
6601         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
6602     }
6603     return WINED3D_OK;
6604 }
6605
6606 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6607     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6608     HRESULT  hr = WINED3D_OK;
6609     IWineD3DSurface *tmp;
6610
6611     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6612
6613     if (pNewZStencil == This->stencilBufferTarget) {
6614         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6615     } else {
6616         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6617         * depending on the renter target implementation being used.
6618         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6619         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6620         * stencil buffer and incur an extra memory overhead
6621          ******************************************************/
6622
6623         if (This->stencilBufferTarget) {
6624             if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
6625                     || ((IWineD3DSurfaceImpl *)This->stencilBufferTarget)->Flags & SFLAG_DISCARD) {
6626                 surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_DISCARDED);
6627             } else {
6628                 ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
6629                 surface_load_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN);
6630                 surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN);
6631             }
6632         }
6633
6634         tmp = This->stencilBufferTarget;
6635         This->stencilBufferTarget = pNewZStencil;
6636         /* should we be calling the parent or the wined3d surface? */
6637         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6638         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6639         hr = WINED3D_OK;
6640
6641         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6642             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6643             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6644             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6645             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6646         }
6647     }
6648
6649     return hr;
6650 }
6651
6652 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6653                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6654     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6655     /* TODO: the use of Impl is deprecated. */
6656     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6657     WINED3DLOCKED_RECT lockedRect;
6658
6659     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6660
6661     /* some basic validation checks */
6662     if(This->cursorTexture) {
6663         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6664         ENTER_GL();
6665         glDeleteTextures(1, &This->cursorTexture);
6666         LEAVE_GL();
6667         This->cursorTexture = 0;
6668     }
6669
6670     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6671         This->haveHardwareCursor = TRUE;
6672     else
6673         This->haveHardwareCursor = FALSE;
6674
6675     if(pCursorBitmap) {
6676         WINED3DLOCKED_RECT rect;
6677
6678         /* MSDN: Cursor must be A8R8G8B8 */
6679         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format_desc->format)
6680         {
6681             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6682             return WINED3DERR_INVALIDCALL;
6683         }
6684
6685         /* MSDN: Cursor must be smaller than the display mode */
6686         if(pSur->currentDesc.Width > This->ddraw_width ||
6687            pSur->currentDesc.Height > This->ddraw_height) {
6688             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);
6689             return WINED3DERR_INVALIDCALL;
6690         }
6691
6692         if (!This->haveHardwareCursor) {
6693             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6694
6695             /* Do not store the surface's pointer because the application may
6696              * release it after setting the cursor image. Windows doesn't
6697              * addref the set surface, so we can't do this either without
6698              * creating circular refcount dependencies. Copy out the gl texture
6699              * instead.
6700              */
6701             This->cursorWidth = pSur->currentDesc.Width;
6702             This->cursorHeight = pSur->currentDesc.Height;
6703             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6704             {
6705                 const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION);
6706                 char *mem, *bits = rect.pBits;
6707                 GLint intfmt = glDesc->glInternal;
6708                 GLint format = glDesc->glFormat;
6709                 GLint type = glDesc->glType;
6710                 INT height = This->cursorHeight;
6711                 INT width = This->cursorWidth;
6712                 INT bpp = glDesc->byte_count;
6713                 INT i, sampler;
6714
6715                 /* Reformat the texture memory (pitch and width can be
6716                  * different) */
6717                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6718                 for(i = 0; i < height; i++)
6719                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6720                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6721
6722                 ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6723
6724                 ENTER_GL();
6725
6726                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6727                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6728                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6729                 }
6730
6731                 /* Make sure that a proper texture unit is selected */
6732                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6733                 checkGLcall("glActiveTextureARB");
6734                 sampler = This->rev_tex_unit_map[0];
6735                 if (sampler != -1) {
6736                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
6737                 }
6738                 /* Create a new cursor texture */
6739                 glGenTextures(1, &This->cursorTexture);
6740                 checkGLcall("glGenTextures");
6741                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6742                 checkGLcall("glBindTexture");
6743                 /* Copy the bitmap memory into the cursor texture */
6744                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6745                 HeapFree(GetProcessHeap(), 0, mem);
6746                 checkGLcall("glTexImage2D");
6747
6748                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6749                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6750                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6751                 }
6752
6753                 LEAVE_GL();
6754             }
6755             else
6756             {
6757                 FIXME("A cursor texture was not returned.\n");
6758                 This->cursorTexture = 0;
6759             }
6760         }
6761         else
6762         {
6763             /* Draw a hardware cursor */
6764             ICONINFO cursorInfo;
6765             HCURSOR cursor;
6766             /* Create and clear maskBits because it is not needed for
6767              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6768              * chunks. */
6769             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6770                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6771             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6772                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6773                                          WINED3DLOCK_READONLY
6774             );
6775             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6776                   pSur->currentDesc.Height);
6777
6778             cursorInfo.fIcon = FALSE;
6779             cursorInfo.xHotspot = XHotSpot;
6780             cursorInfo.yHotspot = YHotSpot;
6781             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
6782                                               pSur->currentDesc.Height, 1,
6783                                               1, &maskBits);
6784             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
6785                                                pSur->currentDesc.Height, 1,
6786                                                32, lockedRect.pBits);
6787             IWineD3DSurface_UnlockRect(pCursorBitmap);
6788             /* Create our cursor and clean up. */
6789             cursor = CreateIconIndirect(&cursorInfo);
6790             SetCursor(cursor);
6791             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6792             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6793             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6794             This->hardwareCursor = cursor;
6795             HeapFree(GetProcessHeap(), 0, maskBits);
6796         }
6797     }
6798
6799     This->xHotSpot = XHotSpot;
6800     This->yHotSpot = YHotSpot;
6801     return WINED3D_OK;
6802 }
6803
6804 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6805     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6806     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6807
6808     This->xScreenSpace = XScreenSpace;
6809     This->yScreenSpace = YScreenSpace;
6810
6811     return;
6812
6813 }
6814
6815 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6816     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6817     BOOL oldVisible = This->bCursorVisible;
6818     POINT pt;
6819
6820     TRACE("(%p) : visible(%d)\n", This, bShow);
6821
6822     /*
6823      * When ShowCursor is first called it should make the cursor appear at the OS's last
6824      * known cursor position.  Because of this, some applications just repetitively call
6825      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6826      */
6827     GetCursorPos(&pt);
6828     This->xScreenSpace = pt.x;
6829     This->yScreenSpace = pt.y;
6830
6831     if (This->haveHardwareCursor) {
6832         This->bCursorVisible = bShow;
6833         if (bShow)
6834             SetCursor(This->hardwareCursor);
6835         else
6836             SetCursor(NULL);
6837     }
6838     else
6839     {
6840         if (This->cursorTexture)
6841             This->bCursorVisible = bShow;
6842     }
6843
6844     return oldVisible;
6845 }
6846
6847 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6848     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6849     IWineD3DResourceImpl *resource;
6850     TRACE("(%p) : state (%u)\n", This, This->state);
6851
6852     /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
6853     switch (This->state) {
6854     case WINED3D_OK:
6855         return WINED3D_OK;
6856     case WINED3DERR_DEVICELOST:
6857         {
6858             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6859                 if (resource->resource.pool == WINED3DPOOL_DEFAULT)
6860                     return WINED3DERR_DEVICENOTRESET;
6861             }
6862             return WINED3DERR_DEVICELOST;
6863         }
6864     case WINED3DERR_DRIVERINTERNALERROR:
6865         return WINED3DERR_DRIVERINTERNALERROR;
6866     }
6867
6868     /* Unknown state */
6869     return WINED3DERR_DRIVERINTERNALERROR;
6870 }
6871
6872 static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) {
6873     TRACE("checking resource %p for eviction\n", resource);
6874     if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) {
6875         TRACE("Evicting %p\n", resource);
6876         IWineD3DResource_UnLoad(resource);
6877     }
6878     IWineD3DResource_Release(resource);
6879     return S_OK;
6880 }
6881
6882 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6883     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6884     TRACE("(%p)\n", This);
6885
6886     IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL);
6887     return WINED3D_OK;
6888 }
6889
6890 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
6891 {
6892     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
6893
6894     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6895     if(surface->Flags & SFLAG_DIBSECTION) {
6896         /* Release the DC */
6897         SelectObject(surface->hDC, surface->dib.holdbitmap);
6898         DeleteDC(surface->hDC);
6899         /* Release the DIB section */
6900         DeleteObject(surface->dib.DIBsection);
6901         surface->dib.bitmap_data = NULL;
6902         surface->resource.allocatedMemory = NULL;
6903         surface->Flags &= ~SFLAG_DIBSECTION;
6904     }
6905     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6906     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6907     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE) ||
6908         GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) {
6909         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6910         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6911     } else {
6912         surface->pow2Width = surface->pow2Height = 1;
6913         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6914         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6915     }
6916     surface->glRect.left = 0;
6917     surface->glRect.top = 0;
6918     surface->glRect.right = surface->pow2Width;
6919     surface->glRect.bottom = surface->pow2Height;
6920
6921     if (surface->texture_name)
6922     {
6923         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6924         ENTER_GL();
6925         glDeleteTextures(1, &surface->texture_name);
6926         LEAVE_GL();
6927         surface->texture_name = 0;
6928         surface->Flags &= ~SFLAG_CLIENT;
6929     }
6930     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6931        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6932         surface->Flags |= SFLAG_NONPOW2;
6933     } else  {
6934         surface->Flags &= ~SFLAG_NONPOW2;
6935     }
6936     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
6937     surface->resource.allocatedMemory = NULL;
6938     surface->resource.heapMemory = NULL;
6939     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6940     /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
6941     if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) {
6942         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INSYSMEM, TRUE);
6943     } else {
6944         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INDRAWABLE, TRUE);
6945     }
6946 }
6947
6948 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6949     TRACE("Unloading resource %p\n", resource);
6950     IWineD3DResource_UnLoad(resource);
6951     IWineD3DResource_Release(resource);
6952     return S_OK;
6953 }
6954
6955 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
6956 {
6957     UINT i, count;
6958     WINED3DDISPLAYMODE m;
6959     HRESULT hr;
6960
6961     /* All Windowed modes are supported, as is leaving the current mode */
6962     if(pp->Windowed) return TRUE;
6963     if(!pp->BackBufferWidth) return TRUE;
6964     if(!pp->BackBufferHeight) return TRUE;
6965
6966     count = IWineD3D_GetAdapterModeCount(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN);
6967     for(i = 0; i < count; i++) {
6968         memset(&m, 0, sizeof(m));
6969         hr = IWineD3D_EnumAdapterModes(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN, i, &m);
6970         if(FAILED(hr)) {
6971             ERR("EnumAdapterModes failed\n");
6972         }
6973         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
6974             /* Mode found, it is supported */
6975             return TRUE;
6976         }
6977     }
6978     /* Mode not found -> not supported */
6979     return FALSE;
6980 }
6981
6982 void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) {
6983     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6984     IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface;
6985     UINT i;
6986     IWineD3DBaseShaderImpl *shader;
6987
6988     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6989
6990     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6991     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6992         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6993     }
6994
6995     ENTER_GL();
6996     if(This->depth_blt_texture) {
6997         glDeleteTextures(1, &This->depth_blt_texture);
6998         This->depth_blt_texture = 0;
6999     }
7000     if (This->depth_blt_rb) {
7001         GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This->depth_blt_rb));
7002         This->depth_blt_rb = 0;
7003         This->depth_blt_rb_w = 0;
7004         This->depth_blt_rb_h = 0;
7005     }
7006     LEAVE_GL();
7007
7008     This->blitter->free_private(iface);
7009     This->frag_pipe->free_private(iface);
7010     This->shader_backend->shader_free_private(iface);
7011
7012     ENTER_GL();
7013     for (i = 0; i < GL_LIMITS(textures); i++) {
7014         /* Textures are recreated below */
7015         glDeleteTextures(1, &This->dummyTextureName[i]);
7016         checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])");
7017         This->dummyTextureName[i] = 0;
7018     }
7019     LEAVE_GL();
7020
7021     while(This->numContexts) {
7022         DestroyContext(This, This->contexts[0]);
7023     }
7024     This->activeContext = NULL;
7025     HeapFree(GetProcessHeap(), 0, swapchain->context);
7026     swapchain->context = NULL;
7027     swapchain->num_contexts = 0;
7028 }
7029
7030 HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) {
7031     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7032     IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface;
7033     HRESULT hr;
7034     IWineD3DSurfaceImpl *target;
7035
7036     /* Recreate the primary swapchain's context */
7037     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
7038     if(swapchain->backBuffer) {
7039         target = (IWineD3DSurfaceImpl *) swapchain->backBuffer[0];
7040     } else {
7041         target = (IWineD3DSurfaceImpl *) swapchain->frontBuffer;
7042     }
7043     swapchain->context[0] = CreateContext(This, target, swapchain->win_handle, FALSE,
7044                                           &swapchain->presentParms);
7045     swapchain->num_contexts = 1;
7046     This->activeContext = swapchain->context[0];
7047
7048     create_dummy_textures(This);
7049
7050     hr = This->shader_backend->shader_alloc_private(iface);
7051     if(FAILED(hr)) {
7052         ERR("Failed to recreate shader private data\n");
7053         goto err_out;
7054     }
7055     hr = This->frag_pipe->alloc_private(iface);
7056     if(FAILED(hr)) {
7057         TRACE("Fragment pipeline private data couldn't be allocated\n");
7058         goto err_out;
7059     }
7060     hr = This->blitter->alloc_private(iface);
7061     if(FAILED(hr)) {
7062         TRACE("Blitter private data couldn't be allocated\n");
7063         goto err_out;
7064     }
7065
7066     return WINED3D_OK;
7067
7068 err_out:
7069     This->blitter->free_private(iface);
7070     This->frag_pipe->free_private(iface);
7071     This->shader_backend->shader_free_private(iface);
7072     return hr;
7073 }
7074
7075 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7076     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7077     IWineD3DSwapChainImpl *swapchain;
7078     HRESULT hr;
7079     BOOL DisplayModeChanged = FALSE;
7080     WINED3DDISPLAYMODE mode;
7081     TRACE("(%p)\n", This);
7082
7083     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
7084     if(FAILED(hr)) {
7085         ERR("Failed to get the first implicit swapchain\n");
7086         return hr;
7087     }
7088
7089     if(!is_display_mode_supported(This, pPresentationParameters)) {
7090         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
7091         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
7092              pPresentationParameters->BackBufferHeight);
7093         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
7094         return WINED3DERR_INVALIDCALL;
7095     }
7096
7097     /* Is it necessary to recreate the gl context? Actually every setting can be changed
7098      * on an existing gl context, so there's no real need for recreation.
7099      *
7100      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7101      *
7102      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7103      */
7104     TRACE("New params:\n");
7105     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
7106     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
7107     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
7108     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
7109     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
7110     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
7111     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
7112     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
7113     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
7114     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
7115     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
7116     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
7117     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
7118
7119     /* No special treatment of these parameters. Just store them */
7120     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
7121     swapchain->presentParms.Flags = pPresentationParameters->Flags;
7122     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
7123     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
7124
7125     /* What to do about these? */
7126     if(pPresentationParameters->BackBufferCount != 0 &&
7127         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
7128         ERR("Cannot change the back buffer count yet\n");
7129     }
7130     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
7131         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
7132         ERR("Cannot change the back buffer format yet\n");
7133     }
7134     if(pPresentationParameters->hDeviceWindow != NULL &&
7135         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
7136         ERR("Cannot change the device window yet\n");
7137     }
7138     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil_buffer) {
7139         HRESULT hrc;
7140
7141         TRACE("Creating the depth stencil buffer\n");
7142
7143         hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
7144                 This->parent,
7145                 pPresentationParameters->BackBufferWidth,
7146                 pPresentationParameters->BackBufferHeight,
7147                 pPresentationParameters->AutoDepthStencilFormat,
7148                 pPresentationParameters->MultiSampleType,
7149                 pPresentationParameters->MultiSampleQuality,
7150                 FALSE,
7151                 &This->auto_depth_stencil_buffer);
7152
7153         if (FAILED(hrc)) {
7154             ERR("Failed to create the depth stencil buffer\n");
7155             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
7156             return WINED3DERR_INVALIDCALL;
7157         }
7158     }
7159
7160     /* Reset the depth stencil */
7161     if (pPresentationParameters->EnableAutoDepthStencil)
7162         IWineD3DDevice_SetDepthStencilSurface(iface, This->auto_depth_stencil_buffer);
7163     else
7164         IWineD3DDevice_SetDepthStencilSurface(iface, NULL);
7165
7166     delete_opengl_contexts(iface, (IWineD3DSwapChain *) swapchain);
7167
7168     if(pPresentationParameters->Windowed) {
7169         mode.Width = swapchain->orig_width;
7170         mode.Height = swapchain->orig_height;
7171         mode.RefreshRate = 0;
7172         mode.Format = swapchain->presentParms.BackBufferFormat;
7173     } else {
7174         mode.Width = pPresentationParameters->BackBufferWidth;
7175         mode.Height = pPresentationParameters->BackBufferHeight;
7176         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
7177         mode.Format = swapchain->presentParms.BackBufferFormat;
7178     }
7179
7180     /* Should Width == 800 && Height == 0 set 800x600? */
7181     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
7182        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
7183         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
7184     {
7185         UINT i;
7186
7187         if(!pPresentationParameters->Windowed) {
7188             DisplayModeChanged = TRUE;
7189         }
7190         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
7191         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
7192
7193         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
7194         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7195             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
7196         }
7197         if(This->auto_depth_stencil_buffer) {
7198             updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters);
7199         }
7200     }
7201
7202     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
7203        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
7204         DisplayModeChanged) {
7205
7206         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
7207
7208         if(swapchain->win_handle && !pPresentationParameters->Windowed) {
7209             if(swapchain->presentParms.Windowed) {
7210                 /* switch from windowed to fs */
7211                 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle,
7212                                                          pPresentationParameters->BackBufferWidth,
7213                                                          pPresentationParameters->BackBufferHeight);
7214             } else {
7215                 /* Fullscreen -> fullscreen mode change */
7216                 MoveWindow(swapchain->win_handle, 0, 0,
7217                            pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
7218                            TRUE);
7219             }
7220         } else if(swapchain->win_handle && !swapchain->presentParms.Windowed) {
7221             /* Fullscreen -> windowed switch */
7222             IWineD3DDeviceImpl_RestoreWindow(iface, swapchain->win_handle);
7223         }
7224         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
7225     } else if(!pPresentationParameters->Windowed) {
7226         DWORD style = This->style, exStyle = This->exStyle;
7227         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
7228          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
7229          * Reset to clear up their mess. Guild Wars also loses the device during that.
7230          */
7231         This->style = 0;
7232         This->exStyle = 0;
7233         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle,
7234                                                  pPresentationParameters->BackBufferWidth,
7235                                                  pPresentationParameters->BackBufferHeight);
7236         This->style = style;
7237         This->exStyle = exStyle;
7238     }
7239
7240     TRACE("Resetting stateblock\n");
7241     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
7242     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
7243
7244     /* Note: No parent needed for initial internal stateblock */
7245     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock, NULL);
7246     if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
7247     else TRACE("Created stateblock %p\n", This->stateBlock);
7248     This->updateStateBlock = This->stateBlock;
7249     IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
7250
7251     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
7252     if(FAILED(hr)) {
7253         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
7254     }
7255
7256     hr = create_primary_opengl_context(iface, (IWineD3DSwapChain *) swapchain);
7257     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
7258
7259     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
7260      * first use
7261      */
7262     return hr;
7263 }
7264
7265 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7266     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7267     /** FIXME: always true at the moment **/
7268     if(!bEnableDialogs) {
7269         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7270     }
7271     return WINED3D_OK;
7272 }
7273
7274
7275 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7276     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7277     TRACE("(%p) : pParameters %p\n", This, pParameters);
7278
7279     *pParameters = This->createParms;
7280     return WINED3D_OK;
7281 }
7282
7283 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7284     IWineD3DSwapChain *swapchain;
7285
7286     TRACE("Relaying  to swapchain\n");
7287
7288     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
7289         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, pRamp);
7290         IWineD3DSwapChain_Release(swapchain);
7291     }
7292     return;
7293 }
7294
7295 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7296     IWineD3DSwapChain *swapchain;
7297
7298     TRACE("Relaying  to swapchain\n");
7299
7300     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
7301         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7302         IWineD3DSwapChain_Release(swapchain);
7303     }
7304     return;
7305 }
7306
7307
7308 /** ********************************************************
7309 *   Notification functions
7310 ** ********************************************************/
7311 /** This function must be called in the release of a resource when ref == 0,
7312 * the contents of resource must still be correct,
7313 * any handles to other resource held by the caller must be closed
7314 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7315  *****************************************************/
7316 void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
7317 {
7318     TRACE("(%p) : Adding resource %p\n", This, resource);
7319
7320     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
7321 }
7322
7323 static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
7324 {
7325     TRACE("(%p) : Removing resource %p\n", This, resource);
7326
7327     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
7328 }
7329
7330 void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
7331 {
7332     WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource);
7333     int counter;
7334
7335     TRACE("(%p) : resource %p\n", This, resource);
7336
7337     context_resource_released((IWineD3DDevice *)This, resource, type);
7338
7339     switch (type) {
7340         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
7341         case WINED3DRTYPE_SURFACE: {
7342             unsigned int i;
7343
7344             if (This->d3d_initialized)
7345             {
7346                 for (i = 0; i < GL_LIMITS(buffers); ++i) {
7347                     if (This->render_targets[i] == (IWineD3DSurface *)resource) {
7348                         This->render_targets[i] = NULL;
7349                     }
7350                 }
7351                 if (This->stencilBufferTarget == (IWineD3DSurface *)resource) {
7352                     This->stencilBufferTarget = NULL;
7353                 }
7354             }
7355
7356             break;
7357         }
7358         case WINED3DRTYPE_TEXTURE:
7359         case WINED3DRTYPE_CUBETEXTURE:
7360         case WINED3DRTYPE_VOLUMETEXTURE:
7361                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
7362                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7363                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7364                         This->stateBlock->textures[counter] = NULL;
7365                     }
7366                     if (This->updateStateBlock != This->stateBlock ){
7367                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7368                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7369                             This->updateStateBlock->textures[counter] = NULL;
7370                         }
7371                     }
7372                 }
7373         break;
7374         case WINED3DRTYPE_VOLUME:
7375         /* TODO: nothing really? */
7376         break;
7377         case WINED3DRTYPE_BUFFER:
7378         {
7379             int streamNumber;
7380             TRACE("Cleaning up stream pointers\n");
7381
7382             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7383                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7384                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7385                 */
7386                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7387                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7388                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7389                         This->updateStateBlock->streamSource[streamNumber] = 0;
7390                         /* Set changed flag? */
7391                     }
7392                 }
7393                 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) */
7394                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7395                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7396                         This->stateBlock->streamSource[streamNumber] = 0;
7397                     }
7398                 }
7399             }
7400
7401             if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7402                 if (This->updateStateBlock->pIndexData == (IWineD3DBuffer *)resource) {
7403                     This->updateStateBlock->pIndexData =  NULL;
7404                 }
7405             }
7406             if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7407                 if (This->stateBlock->pIndexData == (IWineD3DBuffer *)resource) {
7408                     This->stateBlock->pIndexData =  NULL;
7409                 }
7410             }
7411         }
7412         break;
7413
7414         default:
7415         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7416         break;
7417     }
7418
7419
7420     /* Remove the resource from the resourceStore */
7421     device_resource_remove(This, resource);
7422
7423     TRACE("Resource released\n");
7424
7425 }
7426
7427 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
7428     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7429     IWineD3DResourceImpl *resource, *cursor;
7430     HRESULT ret;
7431     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
7432
7433     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
7434         TRACE("enumerating resource %p\n", resource);
7435         IWineD3DResource_AddRef((IWineD3DResource *) resource);
7436         ret = pCallback((IWineD3DResource *) resource, pData);
7437         if(ret == S_FALSE) {
7438             TRACE("Canceling enumeration\n");
7439             break;
7440         }
7441     }
7442     return WINED3D_OK;
7443 }
7444
7445 /**********************************************************
7446  * IWineD3DDevice VTbl follows
7447  **********************************************************/
7448
7449 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7450 {
7451     /*** IUnknown methods ***/
7452     IWineD3DDeviceImpl_QueryInterface,
7453     IWineD3DDeviceImpl_AddRef,
7454     IWineD3DDeviceImpl_Release,
7455     /*** IWineD3DDevice methods ***/
7456     IWineD3DDeviceImpl_GetParent,
7457     /*** Creation methods**/
7458     IWineD3DDeviceImpl_CreateBuffer,
7459     IWineD3DDeviceImpl_CreateVertexBuffer,
7460     IWineD3DDeviceImpl_CreateIndexBuffer,
7461     IWineD3DDeviceImpl_CreateStateBlock,
7462     IWineD3DDeviceImpl_CreateSurface,
7463     IWineD3DDeviceImpl_CreateRendertargetView,
7464     IWineD3DDeviceImpl_CreateTexture,
7465     IWineD3DDeviceImpl_CreateVolumeTexture,
7466     IWineD3DDeviceImpl_CreateVolume,
7467     IWineD3DDeviceImpl_CreateCubeTexture,
7468     IWineD3DDeviceImpl_CreateQuery,
7469     IWineD3DDeviceImpl_CreateSwapChain,
7470     IWineD3DDeviceImpl_CreateVertexDeclaration,
7471     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7472     IWineD3DDeviceImpl_CreateVertexShader,
7473     IWineD3DDeviceImpl_CreatePixelShader,
7474     IWineD3DDeviceImpl_CreatePalette,
7475     /*** Odd functions **/
7476     IWineD3DDeviceImpl_Init3D,
7477     IWineD3DDeviceImpl_InitGDI,
7478     IWineD3DDeviceImpl_Uninit3D,
7479     IWineD3DDeviceImpl_UninitGDI,
7480     IWineD3DDeviceImpl_SetMultithreaded,
7481     IWineD3DDeviceImpl_EvictManagedResources,
7482     IWineD3DDeviceImpl_GetAvailableTextureMem,
7483     IWineD3DDeviceImpl_GetBackBuffer,
7484     IWineD3DDeviceImpl_GetCreationParameters,
7485     IWineD3DDeviceImpl_GetDeviceCaps,
7486     IWineD3DDeviceImpl_GetDirect3D,
7487     IWineD3DDeviceImpl_GetDisplayMode,
7488     IWineD3DDeviceImpl_SetDisplayMode,
7489     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7490     IWineD3DDeviceImpl_GetRasterStatus,
7491     IWineD3DDeviceImpl_GetSwapChain,
7492     IWineD3DDeviceImpl_Reset,
7493     IWineD3DDeviceImpl_SetDialogBoxMode,
7494     IWineD3DDeviceImpl_SetCursorProperties,
7495     IWineD3DDeviceImpl_SetCursorPosition,
7496     IWineD3DDeviceImpl_ShowCursor,
7497     IWineD3DDeviceImpl_TestCooperativeLevel,
7498     /*** Getters and setters **/
7499     IWineD3DDeviceImpl_SetClipPlane,
7500     IWineD3DDeviceImpl_GetClipPlane,
7501     IWineD3DDeviceImpl_SetClipStatus,
7502     IWineD3DDeviceImpl_GetClipStatus,
7503     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7504     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7505     IWineD3DDeviceImpl_SetDepthStencilSurface,
7506     IWineD3DDeviceImpl_GetDepthStencilSurface,
7507     IWineD3DDeviceImpl_SetGammaRamp,
7508     IWineD3DDeviceImpl_GetGammaRamp,
7509     IWineD3DDeviceImpl_SetIndices,
7510     IWineD3DDeviceImpl_GetIndices,
7511     IWineD3DDeviceImpl_SetBaseVertexIndex,
7512     IWineD3DDeviceImpl_GetBaseVertexIndex,
7513     IWineD3DDeviceImpl_SetLight,
7514     IWineD3DDeviceImpl_GetLight,
7515     IWineD3DDeviceImpl_SetLightEnable,
7516     IWineD3DDeviceImpl_GetLightEnable,
7517     IWineD3DDeviceImpl_SetMaterial,
7518     IWineD3DDeviceImpl_GetMaterial,
7519     IWineD3DDeviceImpl_SetNPatchMode,
7520     IWineD3DDeviceImpl_GetNPatchMode,
7521     IWineD3DDeviceImpl_SetPaletteEntries,
7522     IWineD3DDeviceImpl_GetPaletteEntries,
7523     IWineD3DDeviceImpl_SetPixelShader,
7524     IWineD3DDeviceImpl_GetPixelShader,
7525     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7526     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7527     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7528     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7529     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7530     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7531     IWineD3DDeviceImpl_SetRenderState,
7532     IWineD3DDeviceImpl_GetRenderState,
7533     IWineD3DDeviceImpl_SetRenderTarget,
7534     IWineD3DDeviceImpl_GetRenderTarget,
7535     IWineD3DDeviceImpl_SetFrontBackBuffers,
7536     IWineD3DDeviceImpl_SetSamplerState,
7537     IWineD3DDeviceImpl_GetSamplerState,
7538     IWineD3DDeviceImpl_SetScissorRect,
7539     IWineD3DDeviceImpl_GetScissorRect,
7540     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7541     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7542     IWineD3DDeviceImpl_SetStreamSource,
7543     IWineD3DDeviceImpl_GetStreamSource,
7544     IWineD3DDeviceImpl_SetStreamSourceFreq,
7545     IWineD3DDeviceImpl_GetStreamSourceFreq,
7546     IWineD3DDeviceImpl_SetTexture,
7547     IWineD3DDeviceImpl_GetTexture,
7548     IWineD3DDeviceImpl_SetTextureStageState,
7549     IWineD3DDeviceImpl_GetTextureStageState,
7550     IWineD3DDeviceImpl_SetTransform,
7551     IWineD3DDeviceImpl_GetTransform,
7552     IWineD3DDeviceImpl_SetVertexDeclaration,
7553     IWineD3DDeviceImpl_GetVertexDeclaration,
7554     IWineD3DDeviceImpl_SetVertexShader,
7555     IWineD3DDeviceImpl_GetVertexShader,
7556     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7557     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7558     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7559     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7560     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7561     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7562     IWineD3DDeviceImpl_SetViewport,
7563     IWineD3DDeviceImpl_GetViewport,
7564     IWineD3DDeviceImpl_MultiplyTransform,
7565     IWineD3DDeviceImpl_ValidateDevice,
7566     IWineD3DDeviceImpl_ProcessVertices,
7567     /*** State block ***/
7568     IWineD3DDeviceImpl_BeginStateBlock,
7569     IWineD3DDeviceImpl_EndStateBlock,
7570     /*** Scene management ***/
7571     IWineD3DDeviceImpl_BeginScene,
7572     IWineD3DDeviceImpl_EndScene,
7573     IWineD3DDeviceImpl_Present,
7574     IWineD3DDeviceImpl_Clear,
7575     IWineD3DDeviceImpl_ClearRendertargetView,
7576     /*** Drawing ***/
7577     IWineD3DDeviceImpl_SetPrimitiveType,
7578     IWineD3DDeviceImpl_GetPrimitiveType,
7579     IWineD3DDeviceImpl_DrawPrimitive,
7580     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7581     IWineD3DDeviceImpl_DrawPrimitiveUP,
7582     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7583     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7584     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7585     IWineD3DDeviceImpl_DrawRectPatch,
7586     IWineD3DDeviceImpl_DrawTriPatch,
7587     IWineD3DDeviceImpl_DeletePatch,
7588     IWineD3DDeviceImpl_ColorFill,
7589     IWineD3DDeviceImpl_UpdateTexture,
7590     IWineD3DDeviceImpl_UpdateSurface,
7591     IWineD3DDeviceImpl_GetFrontBufferData,
7592     /*** object tracking ***/
7593     IWineD3DDeviceImpl_EnumResources
7594 };
7595
7596 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7597     WINED3DRS_ALPHABLENDENABLE   ,
7598     WINED3DRS_ALPHAFUNC          ,
7599     WINED3DRS_ALPHAREF           ,
7600     WINED3DRS_ALPHATESTENABLE    ,
7601     WINED3DRS_BLENDOP            ,
7602     WINED3DRS_COLORWRITEENABLE   ,
7603     WINED3DRS_DESTBLEND          ,
7604     WINED3DRS_DITHERENABLE       ,
7605     WINED3DRS_FILLMODE           ,
7606     WINED3DRS_FOGDENSITY         ,
7607     WINED3DRS_FOGEND             ,
7608     WINED3DRS_FOGSTART           ,
7609     WINED3DRS_LASTPIXEL          ,
7610     WINED3DRS_SHADEMODE          ,
7611     WINED3DRS_SRCBLEND           ,
7612     WINED3DRS_STENCILENABLE      ,
7613     WINED3DRS_STENCILFAIL        ,
7614     WINED3DRS_STENCILFUNC        ,
7615     WINED3DRS_STENCILMASK        ,
7616     WINED3DRS_STENCILPASS        ,
7617     WINED3DRS_STENCILREF         ,
7618     WINED3DRS_STENCILWRITEMASK   ,
7619     WINED3DRS_STENCILZFAIL       ,
7620     WINED3DRS_TEXTUREFACTOR      ,
7621     WINED3DRS_WRAP0              ,
7622     WINED3DRS_WRAP1              ,
7623     WINED3DRS_WRAP2              ,
7624     WINED3DRS_WRAP3              ,
7625     WINED3DRS_WRAP4              ,
7626     WINED3DRS_WRAP5              ,
7627     WINED3DRS_WRAP6              ,
7628     WINED3DRS_WRAP7              ,
7629     WINED3DRS_ZENABLE            ,
7630     WINED3DRS_ZFUNC              ,
7631     WINED3DRS_ZWRITEENABLE
7632 };
7633
7634 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7635     WINED3DTSS_ALPHAARG0             ,
7636     WINED3DTSS_ALPHAARG1             ,
7637     WINED3DTSS_ALPHAARG2             ,
7638     WINED3DTSS_ALPHAOP               ,
7639     WINED3DTSS_BUMPENVLOFFSET        ,
7640     WINED3DTSS_BUMPENVLSCALE         ,
7641     WINED3DTSS_BUMPENVMAT00          ,
7642     WINED3DTSS_BUMPENVMAT01          ,
7643     WINED3DTSS_BUMPENVMAT10          ,
7644     WINED3DTSS_BUMPENVMAT11          ,
7645     WINED3DTSS_COLORARG0             ,
7646     WINED3DTSS_COLORARG1             ,
7647     WINED3DTSS_COLORARG2             ,
7648     WINED3DTSS_COLOROP               ,
7649     WINED3DTSS_RESULTARG             ,
7650     WINED3DTSS_TEXCOORDINDEX         ,
7651     WINED3DTSS_TEXTURETRANSFORMFLAGS
7652 };
7653
7654 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7655     WINED3DSAMP_ADDRESSU         ,
7656     WINED3DSAMP_ADDRESSV         ,
7657     WINED3DSAMP_ADDRESSW         ,
7658     WINED3DSAMP_BORDERCOLOR      ,
7659     WINED3DSAMP_MAGFILTER        ,
7660     WINED3DSAMP_MINFILTER        ,
7661     WINED3DSAMP_MIPFILTER        ,
7662     WINED3DSAMP_MIPMAPLODBIAS    ,
7663     WINED3DSAMP_MAXMIPLEVEL      ,
7664     WINED3DSAMP_MAXANISOTROPY    ,
7665     WINED3DSAMP_SRGBTEXTURE      ,
7666     WINED3DSAMP_ELEMENTINDEX
7667 };
7668
7669 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7670     WINED3DRS_AMBIENT                       ,
7671     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7672     WINED3DRS_CLIPPING                      ,
7673     WINED3DRS_CLIPPLANEENABLE               ,
7674     WINED3DRS_COLORVERTEX                   ,
7675     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7676     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7677     WINED3DRS_FOGDENSITY                    ,
7678     WINED3DRS_FOGEND                        ,
7679     WINED3DRS_FOGSTART                      ,
7680     WINED3DRS_FOGTABLEMODE                  ,
7681     WINED3DRS_FOGVERTEXMODE                 ,
7682     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7683     WINED3DRS_LIGHTING                      ,
7684     WINED3DRS_LOCALVIEWER                   ,
7685     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7686     WINED3DRS_MULTISAMPLEMASK               ,
7687     WINED3DRS_NORMALIZENORMALS              ,
7688     WINED3DRS_PATCHEDGESTYLE                ,
7689     WINED3DRS_POINTSCALE_A                  ,
7690     WINED3DRS_POINTSCALE_B                  ,
7691     WINED3DRS_POINTSCALE_C                  ,
7692     WINED3DRS_POINTSCALEENABLE              ,
7693     WINED3DRS_POINTSIZE                     ,
7694     WINED3DRS_POINTSIZE_MAX                 ,
7695     WINED3DRS_POINTSIZE_MIN                 ,
7696     WINED3DRS_POINTSPRITEENABLE             ,
7697     WINED3DRS_RANGEFOGENABLE                ,
7698     WINED3DRS_SPECULARMATERIALSOURCE        ,
7699     WINED3DRS_TWEENFACTOR                   ,
7700     WINED3DRS_VERTEXBLEND                   ,
7701     WINED3DRS_CULLMODE                      ,
7702     WINED3DRS_FOGCOLOR
7703 };
7704
7705 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7706     WINED3DTSS_TEXCOORDINDEX         ,
7707     WINED3DTSS_TEXTURETRANSFORMFLAGS
7708 };
7709
7710 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7711     WINED3DSAMP_DMAPOFFSET
7712 };
7713
7714 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7715     DWORD rep = This->StateTable[state].representative;
7716     DWORD idx;
7717     BYTE shift;
7718     UINT i;
7719     WineD3DContext *context;
7720
7721     if(!rep) return;
7722     for(i = 0; i < This->numContexts; i++) {
7723         context = This->contexts[i];
7724         if(isStateDirty(context, rep)) continue;
7725
7726         context->dirtyArray[context->numDirtyEntries++] = rep;
7727         idx = rep >> 5;
7728         shift = rep & 0x1f;
7729         context->isStateDirty[idx] |= (1 << shift);
7730     }
7731 }
7732
7733 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7734     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7735     /* The drawable size of a pbuffer render target is the current pbuffer size
7736      */
7737     *width = dev->pbufferWidth;
7738     *height = dev->pbufferHeight;
7739 }
7740
7741 void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7742     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
7743      */
7744     *width = This->pow2Width;
7745     *height = This->pow2Height;
7746 }
7747
7748 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7749     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7750     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7751      * current context's drawable, which is the size of the back buffer of the swapchain
7752      * the active context belongs to. The back buffer of the swapchain is stored as the
7753      * surface the context belongs to.
7754      */
7755     *width = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Width;
7756     *height = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Height;
7757 }