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