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