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