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