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