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