wined3d: Try to force a top-left filling convention.
[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] = WINED3D_UNMAPPED_STAGE;
2117             This->rev_tex_unit_map[state] = WINED3D_UNMAPPED_STAGE;
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, DWORD stage, DWORD unit)
3639 {
3640     DWORD i = This->rev_tex_unit_map[unit];
3641     DWORD j = This->texUnitMap[stage];
3642
3643     This->texUnitMap[stage] = unit;
3644     if (i != WINED3D_UNMAPPED_STAGE && i != stage)
3645     {
3646         This->texUnitMap[i] = WINED3D_UNMAPPED_STAGE;
3647     }
3648
3649     This->rev_tex_unit_map[unit] = stage;
3650     if (j != WINED3D_UNMAPPED_STAGE && j != unit)
3651     {
3652         This->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE;
3653     }
3654 }
3655
3656 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
3657     int i;
3658
3659     This->fixed_function_usage_map = 0;
3660     for (i = 0; i < MAX_TEXTURES; ++i) {
3661         WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP];
3662         WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP];
3663         DWORD color_arg1 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG1] & WINED3DTA_SELECTMASK;
3664         DWORD color_arg2 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG2] & WINED3DTA_SELECTMASK;
3665         DWORD color_arg3 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG0] & WINED3DTA_SELECTMASK;
3666         DWORD alpha_arg1 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1] & WINED3DTA_SELECTMASK;
3667         DWORD alpha_arg2 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2] & WINED3DTA_SELECTMASK;
3668         DWORD alpha_arg3 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0] & WINED3DTA_SELECTMASK;
3669
3670         if (color_op == WINED3DTOP_DISABLE) {
3671             /* Not used, and disable higher stages */
3672             break;
3673         }
3674
3675         if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG2)
3676                 || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG1)
3677                 || ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP))
3678                 || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
3679                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
3680                 || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
3681             This->fixed_function_usage_map |= (1 << i);
3682         }
3683
3684         if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
3685             This->fixed_function_usage_map |= (1 << (i + 1));
3686         }
3687     }
3688 }
3689
3690 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
3691     unsigned int i, tex;
3692     WORD ffu_map;
3693
3694     device_update_fixed_function_usage_map(This);
3695     ffu_map = This->fixed_function_usage_map;
3696
3697     if (This->max_ffp_textures == This->max_ffp_texture_stages ||
3698             This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) {
3699         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3700         {
3701             if (!(ffu_map & 1)) continue;
3702
3703             if (This->texUnitMap[i] != i) {
3704                 device_map_stage(This, i, i);
3705                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3706                 markTextureStagesDirty(This, i);
3707             }
3708         }
3709         return;
3710     }
3711
3712     /* Now work out the mapping */
3713     tex = 0;
3714     for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3715     {
3716         if (!(ffu_map & 1)) continue;
3717
3718         if (This->texUnitMap[i] != tex) {
3719             device_map_stage(This, i, tex);
3720             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3721             markTextureStagesDirty(This, i);
3722         }
3723
3724         ++tex;
3725     }
3726 }
3727
3728 static void device_map_psamplers(IWineD3DDeviceImpl *This) {
3729     const WINED3DSAMPLER_TEXTURE_TYPE *sampler_type =
3730             ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.sampler_type;
3731     unsigned int i;
3732
3733     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
3734         if (sampler_type[i] && This->texUnitMap[i] != i)
3735         {
3736             device_map_stage(This, i, i);
3737             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3738             if (i < MAX_TEXTURES) {
3739                 markTextureStagesDirty(This, i);
3740             }
3741         }
3742     }
3743 }
3744
3745 static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshader_sampler_tokens,
3746         const DWORD *vshader_sampler_tokens, DWORD unit)
3747 {
3748     DWORD current_mapping = This->rev_tex_unit_map[unit];
3749
3750     /* Not currently used */
3751     if (current_mapping == WINED3D_UNMAPPED_STAGE) return TRUE;
3752
3753     if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
3754         /* Used by a fragment sampler */
3755
3756         if (!pshader_sampler_tokens) {
3757             /* No pixel shader, check fixed function */
3758             return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping));
3759         }
3760
3761         /* Pixel shader, check the shader's sampler map */
3762         return !pshader_sampler_tokens[current_mapping];
3763     }
3764
3765     /* Used by a vertex sampler */
3766     return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS];
3767 }
3768
3769 static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
3770     const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_type =
3771             ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.sampler_type;
3772     const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_type = NULL;
3773     int start = min(MAX_COMBINED_SAMPLERS, GL_LIMITS(combined_samplers)) - 1;
3774     int i;
3775
3776     if (ps) {
3777         IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
3778
3779         /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3780          * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3781         pshader_sampler_type = pshader->baseShader.reg_maps.sampler_type;
3782     }
3783
3784     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
3785         DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
3786         if (vshader_sampler_type[i])
3787         {
3788             if (This->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
3789             {
3790                 /* Already mapped somewhere */
3791                 continue;
3792             }
3793
3794             while (start >= 0) {
3795                 if (device_unit_free_for_vs(This, pshader_sampler_type, vshader_sampler_type, start))
3796                 {
3797                     device_map_stage(This, vsampler_idx, start);
3798                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx));
3799
3800                     --start;
3801                     break;
3802                 }
3803
3804                 --start;
3805             }
3806         }
3807     }
3808 }
3809
3810 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3811     BOOL vs = use_vs(This->stateBlock);
3812     BOOL ps = use_ps(This->stateBlock);
3813     /*
3814      * Rules are:
3815      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3816      * that would be really messy and require shader recompilation
3817      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3818      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3819      */
3820     if (ps) {
3821         device_map_psamplers(This);
3822     } else {
3823         device_map_fixed_function_samplers(This);
3824     }
3825
3826     if (vs) {
3827         device_map_vsamplers(This, ps);
3828     }
3829 }
3830
3831 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3832     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3833     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3834     This->updateStateBlock->pixelShader         = pShader;
3835     This->updateStateBlock->changed.pixelShader = TRUE;
3836
3837     /* Handle recording of state blocks */
3838     if (This->isRecordingState) {
3839         TRACE("Recording... not performing anything\n");
3840     }
3841
3842     if (This->isRecordingState) {
3843         TRACE("Recording... not performing anything\n");
3844         if(pShader) IWineD3DPixelShader_AddRef(pShader);
3845         if(oldShader) IWineD3DPixelShader_Release(oldShader);
3846         return WINED3D_OK;
3847     }
3848
3849     if(pShader == oldShader) {
3850         TRACE("App is setting the old pixel shader over, nothing to do\n");
3851         return WINED3D_OK;
3852     }
3853
3854     if(pShader) IWineD3DPixelShader_AddRef(pShader);
3855     if(oldShader) IWineD3DPixelShader_Release(oldShader);
3856
3857     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3858     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3859
3860     return WINED3D_OK;
3861 }
3862
3863 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3864     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3865
3866     if (NULL == ppShader) {
3867         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3868         return WINED3DERR_INVALIDCALL;
3869     }
3870
3871     *ppShader =  This->stateBlock->pixelShader;
3872     if (NULL != *ppShader) {
3873         IWineD3DPixelShader_AddRef(*ppShader);
3874     }
3875     TRACE("(%p) : returning %p\n", This, *ppShader);
3876     return WINED3D_OK;
3877 }
3878
3879 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3880     IWineD3DDevice *iface,
3881     UINT start,
3882     CONST BOOL *srcData,
3883     UINT count) {
3884
3885     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3886     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3887
3888     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3889             iface, srcData, start, count);
3890
3891     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3892
3893     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3894     for (i = 0; i < cnt; i++)
3895         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3896
3897     for (i = start; i < cnt + start; ++i) {
3898         This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
3899     }
3900
3901     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3902
3903     return WINED3D_OK;
3904 }
3905
3906 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3907     IWineD3DDevice *iface,
3908     UINT start,
3909     BOOL *dstData,
3910     UINT count) {
3911
3912     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3913     int cnt = min(count, MAX_CONST_B - start);
3914
3915     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3916             iface, dstData, start, count);
3917
3918     if (dstData == NULL || cnt < 0)
3919         return WINED3DERR_INVALIDCALL;
3920
3921     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3922     return WINED3D_OK;
3923 }
3924
3925 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3926     IWineD3DDevice *iface,
3927     UINT start,
3928     CONST int *srcData,
3929     UINT count) {
3930
3931     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3932     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3933
3934     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3935             iface, srcData, start, count);
3936
3937     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3938
3939     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3940     for (i = 0; i < cnt; i++)
3941         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3942            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3943
3944     for (i = start; i < cnt + start; ++i) {
3945         This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
3946     }
3947
3948     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3949
3950     return WINED3D_OK;
3951 }
3952
3953 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3954     IWineD3DDevice *iface,
3955     UINT start,
3956     int *dstData,
3957     UINT count) {
3958
3959     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3960     int cnt = min(count, MAX_CONST_I - start);
3961
3962     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3963             iface, dstData, start, count);
3964
3965     if (dstData == NULL || cnt < 0)
3966         return WINED3DERR_INVALIDCALL;
3967
3968     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3969     return WINED3D_OK;
3970 }
3971
3972 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3973     IWineD3DDevice *iface,
3974     UINT start,
3975     CONST float *srcData,
3976     UINT count) {
3977
3978     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3979     UINT i;
3980
3981     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3982             iface, srcData, start, count);
3983
3984     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3985     if (srcData == NULL || start + count > This->d3d_pshader_constantF || start > This->d3d_pshader_constantF)
3986         return WINED3DERR_INVALIDCALL;
3987
3988     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3989     if(TRACE_ON(d3d)) {
3990         for (i = 0; i < count; i++)
3991             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3992                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3993     }
3994
3995     if (!This->isRecordingState)
3996     {
3997         This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
3998         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3999     }
4000
4001     memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
4002             sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
4003
4004     return WINED3D_OK;
4005 }
4006
4007 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4008     IWineD3DDevice *iface,
4009     UINT start,
4010     float *dstData,
4011     UINT count) {
4012
4013     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4014     int cnt = min(count, This->d3d_pshader_constantF - start);
4015
4016     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4017             iface, dstData, start, count);
4018
4019     if (dstData == NULL || cnt < 0)
4020         return WINED3DERR_INVALIDCALL;
4021
4022     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4023     return WINED3D_OK;
4024 }
4025
4026 /* Context activation is done by the caller. */
4027 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4028 static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount,
4029         const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD dwFlags,
4030         DWORD DestFVF)
4031 {
4032     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
4033     unsigned int i;
4034     WINED3DVIEWPORT vp;
4035     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
4036     BOOL doClip;
4037     DWORD numTextures;
4038
4039     if (stream_info->elements[WINED3D_FFP_NORMAL].data)
4040     {
4041         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4042     }
4043
4044     if (!stream_info->elements[WINED3D_FFP_POSITION].data)
4045     {
4046         ERR("Source has no position mask\n");
4047         return WINED3DERR_INVALIDCALL;
4048     }
4049
4050     /* We might access VBOs from this code, so hold the lock */
4051     ENTER_GL();
4052
4053     if (dest->resource.allocatedMemory == NULL) {
4054         buffer_get_sysmem(dest);
4055     }
4056
4057     /* Get a pointer into the destination vbo(create one if none exists) and
4058      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4059      */
4060     if (!dest->buffer_object && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT))
4061     {
4062         dest->flags |= WINED3D_BUFFER_CREATEBO;
4063         IWineD3DBuffer_PreLoad((IWineD3DBuffer *)dest);
4064     }
4065
4066     if (dest->buffer_object)
4067     {
4068         unsigned char extrabytes = 0;
4069         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
4070          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
4071          * this may write 4 extra bytes beyond the area that should be written
4072          */
4073         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
4074         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
4075         if(!dest_conv_addr) {
4076             ERR("Out of memory\n");
4077             /* Continue without storing converted vertices */
4078         }
4079         dest_conv = dest_conv_addr;
4080     }
4081
4082     /* Should I clip?
4083      * a) WINED3DRS_CLIPPING is enabled
4084      * b) WINED3DVOP_CLIP is passed
4085      */
4086     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4087         static BOOL warned = FALSE;
4088         /*
4089          * The clipping code is not quite correct. Some things need
4090          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4091          * so disable clipping for now.
4092          * (The graphics in Half-Life are broken, and my processvertices
4093          *  test crashes with IDirect3DDevice3)
4094         doClip = TRUE;
4095          */
4096         doClip = FALSE;
4097         if(!warned) {
4098            warned = TRUE;
4099            FIXME("Clipping is broken and disabled for now\n");
4100         }
4101     } else doClip = FALSE;
4102     dest_ptr = ((char *) buffer_get_sysmem(dest)) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4103
4104     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4105                                  WINED3DTS_VIEW,
4106                                  &view_mat);
4107     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4108                                  WINED3DTS_PROJECTION,
4109                                  &proj_mat);
4110     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4111                                  WINED3DTS_WORLDMATRIX(0),
4112                                  &world_mat);
4113
4114     TRACE("View mat:\n");
4115     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);
4116     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);
4117     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);
4118     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);
4119
4120     TRACE("Proj mat:\n");
4121     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);
4122     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);
4123     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);
4124     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);
4125
4126     TRACE("World mat:\n");
4127     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);
4128     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);
4129     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);
4130     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);
4131
4132     /* Get the viewport */
4133     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4134     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4135           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4136
4137     multiply_matrix(&mat,&view_mat,&world_mat);
4138     multiply_matrix(&mat,&proj_mat,&mat);
4139
4140     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
4141
4142     for (i = 0; i < dwCount; i+= 1) {
4143         unsigned int tex_index;
4144
4145         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
4146              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
4147             /* The position first */
4148             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
4149             const float *p = (const float *)(element->data + i * element->stride);
4150             float x, y, z, rhw;
4151             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4152
4153             /* Multiplication with world, view and projection matrix */
4154             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);
4155             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);
4156             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);
4157             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);
4158
4159             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4160
4161             /* WARNING: The following things are taken from d3d7 and were not yet checked
4162              * against d3d8 or d3d9!
4163              */
4164
4165             /* Clipping conditions: From msdn
4166              *
4167              * A vertex is clipped if it does not match the following requirements
4168              * -rhw < x <= rhw
4169              * -rhw < y <= rhw
4170              *    0 < z <= rhw
4171              *    0 < rhw ( Not in d3d7, but tested in d3d7)
4172              *
4173              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4174              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4175              *
4176              */
4177
4178             if( !doClip ||
4179                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4180                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
4181                   ( rhw > eps ) ) ) {
4182
4183                 /* "Normal" viewport transformation (not clipped)
4184                  * 1) The values are divided by rhw
4185                  * 2) The y axis is negative, so multiply it with -1
4186                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4187                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4188                  * 4) Multiply x with Width/2 and add Width/2
4189                  * 5) The same for the height
4190                  * 6) Add the viewpoint X and Y to the 2D coordinates and
4191                  *    The minimum Z value to z
4192                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4193                  *
4194                  * Well, basically it's simply a linear transformation into viewport
4195                  * coordinates
4196                  */
4197
4198                 x /= rhw;
4199                 y /= rhw;
4200                 z /= rhw;
4201
4202                 y *= -1;
4203
4204                 x *= vp.Width / 2;
4205                 y *= vp.Height / 2;
4206                 z *= vp.MaxZ - vp.MinZ;
4207
4208                 x += vp.Width / 2 + vp.X;
4209                 y += vp.Height / 2 + vp.Y;
4210                 z += vp.MinZ;
4211
4212                 rhw = 1 / rhw;
4213             } else {
4214                 /* That vertex got clipped
4215                  * Contrary to OpenGL it is not dropped completely, it just
4216                  * undergoes a different calculation.
4217                  */
4218                 TRACE("Vertex got clipped\n");
4219                 x += rhw;
4220                 y += rhw;
4221
4222                 x  /= 2;
4223                 y  /= 2;
4224
4225                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4226                  * outside of the main vertex buffer memory. That needs some more
4227                  * investigation...
4228                  */
4229             }
4230
4231             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4232
4233
4234             ( (float *) dest_ptr)[0] = x;
4235             ( (float *) dest_ptr)[1] = y;
4236             ( (float *) dest_ptr)[2] = z;
4237             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4238
4239             dest_ptr += 3 * sizeof(float);
4240
4241             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4242                 dest_ptr += sizeof(float);
4243             }
4244
4245             if(dest_conv) {
4246                 float w = 1 / rhw;
4247                 ( (float *) dest_conv)[0] = x * w;
4248                 ( (float *) dest_conv)[1] = y * w;
4249                 ( (float *) dest_conv)[2] = z * w;
4250                 ( (float *) dest_conv)[3] = w;
4251
4252                 dest_conv += 3 * sizeof(float);
4253
4254                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4255                     dest_conv += sizeof(float);
4256                 }
4257             }
4258         }
4259         if (DestFVF & WINED3DFVF_PSIZE) {
4260             dest_ptr += sizeof(DWORD);
4261             if(dest_conv) dest_conv += sizeof(DWORD);
4262         }
4263         if (DestFVF & WINED3DFVF_NORMAL) {
4264             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
4265             const float *normal = (const float *)(element->data + i * element->stride);
4266             /* AFAIK this should go into the lighting information */
4267             FIXME("Didn't expect the destination to have a normal\n");
4268             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4269             if(dest_conv) {
4270                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4271             }
4272         }
4273
4274         if (DestFVF & WINED3DFVF_DIFFUSE) {
4275             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
4276             const DWORD *color_d = (const DWORD *)(element->data + i * element->stride);
4277             if(!color_d) {
4278                 static BOOL warned = FALSE;
4279
4280                 if(!warned) {
4281                     ERR("No diffuse color in source, but destination has one\n");
4282                     warned = TRUE;
4283                 }
4284
4285                 *( (DWORD *) dest_ptr) = 0xffffffff;
4286                 dest_ptr += sizeof(DWORD);
4287
4288                 if(dest_conv) {
4289                     *( (DWORD *) dest_conv) = 0xffffffff;
4290                     dest_conv += sizeof(DWORD);
4291                 }
4292             }
4293             else {
4294                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4295                 if(dest_conv) {
4296                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4297                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4298                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4299                     dest_conv += sizeof(DWORD);
4300                 }
4301             }
4302         }
4303
4304         if (DestFVF & WINED3DFVF_SPECULAR) { 
4305             /* What's the color value in the feedback buffer? */
4306             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
4307             const DWORD *color_s = (const DWORD *)(element->data + i * element->stride);
4308             if(!color_s) {
4309                 static BOOL warned = FALSE;
4310
4311                 if(!warned) {
4312                     ERR("No specular color in source, but destination has one\n");
4313                     warned = TRUE;
4314                 }
4315
4316                 *( (DWORD *) dest_ptr) = 0xFF000000;
4317                 dest_ptr += sizeof(DWORD);
4318
4319                 if(dest_conv) {
4320                     *( (DWORD *) dest_conv) = 0xFF000000;
4321                     dest_conv += sizeof(DWORD);
4322                 }
4323             }
4324             else {
4325                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4326                 if(dest_conv) {
4327                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4328                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4329                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4330                     dest_conv += sizeof(DWORD);
4331                 }
4332             }
4333         }
4334
4335         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4336             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
4337             const float *tex_coord = (const float *)(element->data + i * element->stride);
4338             if(!tex_coord) {
4339                 ERR("No source texture, but destination requests one\n");
4340                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4341                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4342             }
4343             else {
4344                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4345                 if(dest_conv) {
4346                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4347                 }
4348             }
4349         }
4350     }
4351
4352     if(dest_conv) {
4353         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->buffer_object));
4354         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4355         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
4356                                       dwCount * get_flexible_vertex_size(DestFVF),
4357                                       dest_conv_addr));
4358         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4359         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
4360     }
4361
4362     LEAVE_GL();
4363
4364     return WINED3D_OK;
4365 }
4366 #undef copy_and_next
4367
4368 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex,
4369         UINT VertexCount, IWineD3DBuffer *pDestBuffer, IWineD3DVertexDeclaration *pVertexDecl, DWORD Flags,
4370         DWORD DestFVF)
4371 {
4372     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4373     struct wined3d_stream_info stream_info;
4374     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
4375     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4376
4377     if(pVertexDecl) {
4378         ERR("Output vertex declaration not implemented yet\n");
4379     }
4380
4381     /* Need any context to write to the vbo. */
4382     ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
4383
4384     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4385      * control the streamIsUP flag, thus restore it afterwards.
4386      */
4387     This->stateBlock->streamIsUP = FALSE;
4388     device_stream_info_from_declaration(This, FALSE, &stream_info, &vbo);
4389     This->stateBlock->streamIsUP = streamWasUP;
4390
4391     if(vbo || SrcStartIndex) {
4392         unsigned int i;
4393         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4394          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4395          *
4396          * Also get the start index in, but only loop over all elements if there's something to add at all.
4397          */
4398         for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
4399         {
4400             struct wined3d_stream_info_element *e = &stream_info.elements[i];
4401             if (e->buffer_object)
4402             {
4403                 struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx];
4404                 e->buffer_object = 0;
4405                 e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb));
4406                 ENTER_GL();
4407                 GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
4408                 vb->buffer_object = 0;
4409                 LEAVE_GL();
4410             }
4411             if (e->data) e->data += e->stride * SrcStartIndex;
4412         }
4413     }
4414
4415     return process_vertices_strided(This, DestIndex, VertexCount, &stream_info,
4416             (struct wined3d_buffer *)pDestBuffer, Flags, DestFVF);
4417 }
4418
4419 /*****
4420  * Get / Set Texture Stage States
4421  * TODO: Verify against dx9 definitions
4422  *****/
4423 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4424     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4425     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4426
4427     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4428
4429     if (Stage >= MAX_TEXTURES) {
4430         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
4431         return WINED3D_OK;
4432     }
4433
4434     This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
4435     This->updateStateBlock->textureState[Stage][Type]         = Value;
4436
4437     if (This->isRecordingState) {
4438         TRACE("Recording... not performing anything\n");
4439         return WINED3D_OK;
4440     }
4441
4442     /* Checked after the assignments to allow proper stateblock recording */
4443     if(oldValue == Value) {
4444         TRACE("App is setting the old value over, nothing to do\n");
4445         return WINED3D_OK;
4446     }
4447
4448     if(Stage > This->stateBlock->lowest_disabled_stage &&
4449        This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4450         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4451          * Changes in other states are important on disabled stages too
4452          */
4453         return WINED3D_OK;
4454     }
4455
4456     if(Type == WINED3DTSS_COLOROP) {
4457         unsigned int i;
4458
4459         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4460             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4461              * they have to be disabled
4462              *
4463              * The current stage is dirtified below.
4464              */
4465             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4466                 TRACE("Additionally dirtifying stage %u\n", i);
4467                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4468             }
4469             This->stateBlock->lowest_disabled_stage = Stage;
4470             TRACE("New lowest disabled: %u\n", Stage);
4471         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4472             /* Previously disabled stage enabled. Stages above it may need enabling
4473              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4474              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4475              *
4476              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4477              */
4478
4479             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4480                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4481                     break;
4482                 }
4483                 TRACE("Additionally dirtifying stage %u due to enable\n", i);
4484                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4485             }
4486             This->stateBlock->lowest_disabled_stage = i;
4487             TRACE("New lowest disabled: %u\n", i);
4488         }
4489     }
4490
4491     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4492
4493     return WINED3D_OK;
4494 }
4495
4496 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4497     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4498     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4499     *pValue = This->updateStateBlock->textureState[Stage][Type];
4500     return WINED3D_OK;
4501 }
4502
4503 /*****
4504  * Get / Set Texture
4505  *****/
4506 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4507     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4508     IWineD3DBaseTexture *oldTexture;
4509
4510     TRACE("(%p) : Stage %#x, Texture %p\n", This, Stage, pTexture);
4511
4512     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4513         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4514     }
4515
4516     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4517         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4518         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4519     }
4520
4521     oldTexture = This->updateStateBlock->textures[Stage];
4522
4523     /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4524     if (pTexture && ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH)
4525     {
4526         WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4527         return WINED3DERR_INVALIDCALL;
4528     }
4529
4530     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4531     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4532
4533     This->updateStateBlock->changed.textures |= 1 << Stage;
4534     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4535     This->updateStateBlock->textures[Stage]         = pTexture;
4536
4537     /* Handle recording of state blocks */
4538     if (This->isRecordingState) {
4539         TRACE("Recording... not performing anything\n");
4540         return WINED3D_OK;
4541     }
4542
4543     if(oldTexture == pTexture) {
4544         TRACE("App is setting the same texture again, nothing to do\n");
4545         return WINED3D_OK;
4546     }
4547
4548     /** NOTE: MSDN says that setTexture increases the reference count,
4549     * and that the application must set the texture back to null (or have a leaky application),
4550     * This means we should pass the refcount up to the parent
4551      *******************************/
4552     if (NULL != This->updateStateBlock->textures[Stage]) {
4553         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4554         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4555         UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4556
4557         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4558
4559         if (!oldTexture || dimensions != IWineD3DBaseTexture_GetTextureDimensions(oldTexture))
4560         {
4561             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
4562         }
4563
4564         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4565             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4566              * so the COLOROP and ALPHAOP have to be dirtified.
4567              */
4568             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4569             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4570         }
4571         if(bindCount == 1) {
4572             new->baseTexture.sampler = Stage;
4573         }
4574         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4575
4576     }
4577
4578     if (NULL != oldTexture) {
4579         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4580         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4581
4582         IWineD3DBaseTexture_Release(oldTexture);
4583         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4584             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4585             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4586         }
4587
4588         if(bindCount && old->baseTexture.sampler == Stage) {
4589             int i;
4590             /* Have to do a search for the other sampler(s) where the texture is bound to
4591              * Shouldn't happen as long as apps bind a texture only to one stage
4592              */
4593             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4594             for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
4595                 if(This->updateStateBlock->textures[i] == oldTexture) {
4596                     old->baseTexture.sampler = i;
4597                     break;
4598                 }
4599             }
4600         }
4601     }
4602
4603     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4604
4605     return WINED3D_OK;
4606 }
4607
4608 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4609     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4610
4611     TRACE("(%p) : Stage %#x, ppTexture %p\n", This, Stage, ppTexture);
4612
4613     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4614         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4615     }
4616
4617     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4618         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4619         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4620     }
4621
4622     *ppTexture=This->stateBlock->textures[Stage];
4623     if (*ppTexture)
4624         IWineD3DBaseTexture_AddRef(*ppTexture);
4625
4626     TRACE("(%p) : Returning %p\n", This, *ppTexture);
4627
4628     return WINED3D_OK;
4629 }
4630
4631 /*****
4632  * Get Back Buffer
4633  *****/
4634 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4635                                                 IWineD3DSurface **ppBackBuffer) {
4636     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4637     IWineD3DSwapChain *swapChain;
4638     HRESULT hr;
4639
4640     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4641
4642     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4643     if (hr == WINED3D_OK) {
4644         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4645             IWineD3DSwapChain_Release(swapChain);
4646     } else {
4647         *ppBackBuffer = NULL;
4648     }
4649     return hr;
4650 }
4651
4652 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4653     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4654     WARN("(%p) : stub, calling idirect3d for now\n", This);
4655     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4656 }
4657
4658 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4659     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4660     IWineD3DSwapChain *swapChain;
4661     HRESULT hr;
4662
4663     if(iSwapChain > 0) {
4664         hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4665         if (hr == WINED3D_OK) {
4666             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4667             IWineD3DSwapChain_Release(swapChain);
4668         } else {
4669             FIXME("(%p) Error getting display mode\n", This);
4670         }
4671     } else {
4672         /* Don't read the real display mode,
4673            but return the stored mode instead. X11 can't change the color
4674            depth, and some apps are pretty angry if they SetDisplayMode from
4675            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4676
4677            Also don't relay to the swapchain because with ddraw it's possible
4678            that there isn't a swapchain at all */
4679         pMode->Width = This->ddraw_width;
4680         pMode->Height = This->ddraw_height;
4681         pMode->Format = This->ddraw_format;
4682         pMode->RefreshRate = 0;
4683         hr = WINED3D_OK;
4684     }
4685
4686     return hr;
4687 }
4688
4689 /*****
4690  * Stateblock related functions
4691  *****/
4692
4693 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4695     IWineD3DStateBlock *stateblock;
4696     HRESULT hr;
4697
4698     TRACE("(%p)\n", This);
4699
4700     if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
4701
4702     hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock, NULL);
4703     if (FAILED(hr)) return hr;
4704
4705     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4706     This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
4707     This->isRecordingState = TRUE;
4708
4709     TRACE("(%p) recording stateblock %p\n", This, stateblock);
4710
4711     return WINED3D_OK;
4712 }
4713
4714 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4715     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4716     unsigned int i, j;
4717     IWineD3DStateBlockImpl *object = This->updateStateBlock;
4718
4719     if (!This->isRecordingState) {
4720         WARN("(%p) not recording! returning error\n", This);
4721         *ppStateBlock = NULL;
4722         return WINED3DERR_INVALIDCALL;
4723     }
4724
4725     for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
4726     {
4727         DWORD map = object->changed.renderState[i];
4728         for (j = 0; map; map >>= 1, ++j)
4729         {
4730             if (!(map & 1)) continue;
4731
4732             object->contained_render_states[object->num_contained_render_states++] = (i << 5) | j;
4733         }
4734     }
4735
4736     for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
4737     {
4738         DWORD map = object->changed.transform[i];
4739         for (j = 0; map; map >>= 1, ++j)
4740         {
4741             if (!(map & 1)) continue;
4742
4743             object->contained_transform_states[object->num_contained_transform_states++] = (i << 5) | j;
4744         }
4745     }
4746     for(i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
4747         if(object->changed.vertexShaderConstantsF[i]) {
4748             object->contained_vs_consts_f[object->num_contained_vs_consts_f] = i;
4749             object->num_contained_vs_consts_f++;
4750         }
4751     }
4752     for(i = 0; i < MAX_CONST_I; i++) {
4753         if (object->changed.vertexShaderConstantsI & (1 << i))
4754         {
4755             object->contained_vs_consts_i[object->num_contained_vs_consts_i] = i;
4756             object->num_contained_vs_consts_i++;
4757         }
4758     }
4759     for(i = 0; i < MAX_CONST_B; i++) {
4760         if (object->changed.vertexShaderConstantsB & (1 << i))
4761         {
4762             object->contained_vs_consts_b[object->num_contained_vs_consts_b] = i;
4763             object->num_contained_vs_consts_b++;
4764         }
4765     }
4766     for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
4767     {
4768         if (object->changed.pixelShaderConstantsF[i])
4769         {
4770             object->contained_ps_consts_f[object->num_contained_ps_consts_f] = i;
4771             ++object->num_contained_ps_consts_f;
4772         }
4773     }
4774     for(i = 0; i < MAX_CONST_I; i++) {
4775         if (object->changed.pixelShaderConstantsI & (1 << i))
4776         {
4777             object->contained_ps_consts_i[object->num_contained_ps_consts_i] = i;
4778             object->num_contained_ps_consts_i++;
4779         }
4780     }
4781     for(i = 0; i < MAX_CONST_B; i++) {
4782         if (object->changed.pixelShaderConstantsB & (1 << i))
4783         {
4784             object->contained_ps_consts_b[object->num_contained_ps_consts_b] = i;
4785             object->num_contained_ps_consts_b++;
4786         }
4787     }
4788     for(i = 0; i < MAX_TEXTURES; i++) {
4789         DWORD map = object->changed.textureState[i];
4790
4791         for(j = 0; map; map >>= 1, ++j)
4792         {
4793             if (!(map & 1)) continue;
4794
4795             object->contained_tss_states[object->num_contained_tss_states].stage = i;
4796             object->contained_tss_states[object->num_contained_tss_states].state = j;
4797             ++object->num_contained_tss_states;
4798         }
4799     }
4800     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){
4801         DWORD map = object->changed.samplerState[i];
4802
4803         for (j = 0; map; map >>= 1, ++j)
4804         {
4805             if (!(map & 1)) continue;
4806
4807             object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
4808             object->contained_sampler_states[object->num_contained_sampler_states].state = j;
4809             ++object->num_contained_sampler_states;
4810         }
4811     }
4812
4813     *ppStateBlock = (IWineD3DStateBlock*) object;
4814     This->isRecordingState = FALSE;
4815     This->updateStateBlock = This->stateBlock;
4816     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4817     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4818     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4819     return WINED3D_OK;
4820 }
4821
4822 /*****
4823  * Scene related functions
4824  *****/
4825 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4826     /* At the moment we have no need for any functionality at the beginning
4827        of a scene                                                          */
4828     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4829     TRACE("(%p)\n", This);
4830
4831     if(This->inScene) {
4832         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4833         return WINED3DERR_INVALIDCALL;
4834     }
4835     This->inScene = TRUE;
4836     return WINED3D_OK;
4837 }
4838
4839 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4840     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4841     TRACE("(%p)\n", This);
4842
4843     if(!This->inScene) {
4844         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4845         return WINED3DERR_INVALIDCALL;
4846     }
4847
4848     ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
4849     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4850     glFlush();
4851     /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4852      * fails
4853      */
4854
4855     This->inScene = FALSE;
4856     return WINED3D_OK;
4857 }
4858
4859 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4860                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4861                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4862     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4863     IWineD3DSwapChain *swapChain = NULL;
4864     int i;
4865     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4866
4867     TRACE("(%p) Presenting the frame\n", This);
4868
4869     for(i = 0 ; i < swapchains ; i ++) {
4870
4871         IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain);
4872         TRACE("presentinng chain %d, %p\n", i, swapChain);
4873         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4874         IWineD3DSwapChain_Release(swapChain);
4875     }
4876
4877     return WINED3D_OK;
4878 }
4879
4880 /* Not called from the VTable (internal subroutine) */
4881 HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfaceImpl *target, DWORD Count,
4882                                         CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
4883                                         float Z, DWORD Stencil) {
4884     GLbitfield     glMask = 0;
4885     unsigned int   i;
4886     WINED3DRECT curRect;
4887     RECT vp_rect;
4888     const WINED3DVIEWPORT *vp = &This->stateBlock->viewport;
4889     UINT drawable_width, drawable_height;
4890     IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget;
4891     IWineD3DSwapChainImpl *swapchain = NULL;
4892     struct wined3d_context *context;
4893
4894     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4895      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4896      * for the cleared parts, and the untouched parts.
4897      *
4898      * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4899      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4900      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4901      * checking all this if the dest surface is in the drawable anyway.
4902      */
4903     if((Flags & WINED3DCLEAR_TARGET) && !(target->Flags & SFLAG_INDRAWABLE)) {
4904         while(1) {
4905             if(vp->X != 0 || vp->Y != 0 ||
4906                vp->Width < target->currentDesc.Width || vp->Height < target->currentDesc.Height) {
4907                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4908                 break;
4909             }
4910             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4911                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4912                This->stateBlock->scissorRect.right < target->currentDesc.Width ||
4913                This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) {
4914                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4915                 break;
4916             }
4917             if(Count > 0 && pRects && (
4918                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4919                pRects[0].x2 < target->currentDesc.Width ||
4920                pRects[0].y2 < target->currentDesc.Height)) {
4921                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4922                 break;
4923             }
4924             break;
4925         }
4926     }
4927
4928     context = ActivateContext(This, (IWineD3DSurface *)target, CTXUSAGE_CLEAR);
4929
4930     target->get_drawable_size(context, &drawable_width, &drawable_height);
4931
4932     ENTER_GL();
4933
4934     /* Only set the values up once, as they are not changing */
4935     if (Flags & WINED3DCLEAR_STENCIL) {
4936         glClearStencil(Stencil);
4937         checkGLcall("glClearStencil");
4938         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4939         glStencilMask(0xFFFFFFFF);
4940     }
4941
4942     if (Flags & WINED3DCLEAR_ZBUFFER) {
4943         DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
4944         glDepthMask(GL_TRUE);
4945         glClearDepth(Z);
4946         checkGLcall("glClearDepth");
4947         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4948         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4949
4950         if (vp->X != 0 || vp->Y != 0 ||
4951                 vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) {
4952             surface_load_ds_location(This->stencilBufferTarget, context, location);
4953         }
4954         else if (This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4955                 This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4956                 This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width ||
4957                 This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) {
4958             surface_load_ds_location(This->stencilBufferTarget, context, location);
4959         }
4960         else if (Count > 0 && pRects && (
4961                 pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4962                 pRects[0].x2 < depth_stencil->currentDesc.Width ||
4963                 pRects[0].y2 < depth_stencil->currentDesc.Height)) {
4964             surface_load_ds_location(This->stencilBufferTarget, context, location);
4965         }
4966     }
4967
4968     if (Flags & WINED3DCLEAR_TARGET) {
4969         TRACE("Clearing screen with glClear to color %x\n", Color);
4970         glClearColor(D3DCOLOR_R(Color),
4971                      D3DCOLOR_G(Color),
4972                      D3DCOLOR_B(Color),
4973                      D3DCOLOR_A(Color));
4974         checkGLcall("glClearColor");
4975
4976         /* Clear ALL colors! */
4977         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4978         glMask = glMask | GL_COLOR_BUFFER_BIT;
4979     }
4980
4981     vp_rect.left = vp->X;
4982     vp_rect.top = vp->Y;
4983     vp_rect.right = vp->X + vp->Width;
4984     vp_rect.bottom = vp->Y + vp->Height;
4985     if (!(Count > 0 && pRects)) {
4986         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4987             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
4988         }
4989         if (context->render_offscreen)
4990         {
4991             glScissor(vp_rect.left, vp_rect.top,
4992                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4993         } else {
4994             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
4995                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4996         }
4997         checkGLcall("glScissor");
4998         glClear(glMask);
4999         checkGLcall("glClear");
5000     } else {
5001         /* Now process each rect in turn */
5002         for (i = 0; i < Count; i++) {
5003             /* Note gl uses lower left, width/height */
5004             IntersectRect((RECT *)&curRect, &vp_rect, (const RECT *)&pRects[i]);
5005             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5006                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
5007             }
5008             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
5009                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
5010                   curRect.x1, (target->currentDesc.Height - curRect.y2),
5011                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5012
5013             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
5014              * The rectangle is not cleared, no error is returned, but further rectanlges are
5015              * still cleared if they are valid
5016              */
5017             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
5018                 TRACE("Rectangle with negative dimensions, ignoring\n");
5019                 continue;
5020             }
5021
5022             if (context->render_offscreen)
5023             {
5024                 glScissor(curRect.x1, curRect.y1,
5025                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5026             } else {
5027                 glScissor(curRect.x1, drawable_height - curRect.y2,
5028                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5029             }
5030             checkGLcall("glScissor");
5031
5032             glClear(glMask);
5033             checkGLcall("glClear");
5034         }
5035     }
5036
5037     /* Restore the old values (why..?) */
5038     if (Flags & WINED3DCLEAR_STENCIL) {
5039         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5040     }
5041     if (Flags & WINED3DCLEAR_TARGET) {
5042         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
5043         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5044                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5045                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
5046                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5047
5048         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
5049          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
5050          */
5051         IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE);
5052     }
5053     if (Flags & WINED3DCLEAR_ZBUFFER) {
5054         /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
5055         DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
5056         surface_modify_ds_location(This->stencilBufferTarget, location);
5057     }
5058
5059     LEAVE_GL();
5060
5061     if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)target, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
5062         if (target == (IWineD3DSurfaceImpl*) swapchain->frontBuffer) {
5063             glFlush();
5064         }
5065         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5066     }
5067
5068     return WINED3D_OK;
5069 }
5070
5071 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
5072                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
5073     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5074     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
5075
5076     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
5077           Count, pRects, Flags, Color, Z, Stencil);
5078
5079     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
5080         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
5081         /* TODO: What about depth stencil buffers without stencil bits? */
5082         return WINED3DERR_INVALIDCALL;
5083     }
5084
5085     return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil);
5086 }
5087
5088 /*****
5089  * Drawing functions
5090  *****/
5091
5092 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
5093         WINED3DPRIMITIVETYPE primitive_type)
5094 {
5095     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5096
5097     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
5098
5099     This->updateStateBlock->changed.primitive_type = TRUE;
5100     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
5101 }
5102
5103 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
5104         WINED3DPRIMITIVETYPE *primitive_type)
5105 {
5106     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5107
5108     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
5109
5110     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
5111
5112     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
5113 }
5114
5115 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
5116 {
5117     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5118
5119     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
5120
5121     if(!This->stateBlock->vertexDecl) {
5122         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5123         return WINED3DERR_INVALIDCALL;
5124     }
5125
5126     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
5127     if(This->stateBlock->streamIsUP) {
5128         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5129         This->stateBlock->streamIsUP = FALSE;
5130     }
5131
5132     if(This->stateBlock->loadBaseVertexIndex != 0) {
5133         This->stateBlock->loadBaseVertexIndex = 0;
5134         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5135     }
5136     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
5137     drawPrimitive(iface, vertex_count, 0/* NumVertices */, StartVertex /* start_idx */,
5138                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5139     return WINED3D_OK;
5140 }
5141
5142 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5143         UINT minIndex, UINT NumVertices, UINT startIndex, UINT index_count)
5144 {
5145     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5146     UINT                 idxStride = 2;
5147     IWineD3DBuffer *pIB;
5148     GLuint vbo;
5149
5150     pIB = This->stateBlock->pIndexData;
5151     if (!pIB) {
5152         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5153          * without an index buffer set. (The first time at least...)
5154          * D3D8 simply dies, but I doubt it can do much harm to return
5155          * D3DERR_INVALIDCALL there as well. */
5156         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
5157         return WINED3DERR_INVALIDCALL;
5158     }
5159
5160     if(!This->stateBlock->vertexDecl) {
5161         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5162         return WINED3DERR_INVALIDCALL;
5163     }
5164
5165     if(This->stateBlock->streamIsUP) {
5166         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5167         This->stateBlock->streamIsUP = FALSE;
5168     }
5169     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
5170
5171     TRACE("(%p) : min %u, vertex count %u, startIdx %u, index count %u\n",
5172             This, minIndex, NumVertices, startIndex, index_count);
5173
5174     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
5175         idxStride = 2;
5176     } else {
5177         idxStride = 4;
5178     }
5179
5180     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
5181         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
5182         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5183     }
5184
5185     drawPrimitive(iface, index_count, NumVertices, startIndex, idxStride,
5186             vbo ? NULL : ((struct wined3d_buffer *) pIB)->resource.allocatedMemory, minIndex);
5187
5188     return WINED3D_OK;
5189 }
5190
5191 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
5192         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
5193 {
5194     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5195     IWineD3DBuffer *vb;
5196
5197     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
5198             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
5199
5200     if(!This->stateBlock->vertexDecl) {
5201         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5202         return WINED3DERR_INVALIDCALL;
5203     }
5204
5205     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5206     vb = This->stateBlock->streamSource[0];
5207     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
5208     if (vb) IWineD3DBuffer_Release(vb);
5209     This->stateBlock->streamOffset[0] = 0;
5210     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5211     This->stateBlock->streamIsUP = TRUE;
5212     This->stateBlock->loadBaseVertexIndex = 0;
5213
5214     /* TODO: Only mark dirty if drawing from a different UP address */
5215     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5216
5217     drawPrimitive(iface, vertex_count, 0 /* NumVertices */, 0 /* start_idx */,
5218             0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5219
5220     /* MSDN specifies stream zero settings must be set to NULL */
5221     This->stateBlock->streamStride[0] = 0;
5222     This->stateBlock->streamSource[0] = NULL;
5223
5224     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5225      * the new stream sources or use UP drawing again
5226      */
5227     return WINED3D_OK;
5228 }
5229
5230 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, UINT MinVertexIndex,
5231         UINT NumVertices, UINT index_count, const void *pIndexData, WINED3DFORMAT IndexDataFormat,
5232         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
5233 {
5234     int                 idxStride;
5235     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5236     IWineD3DBuffer *vb;
5237     IWineD3DBuffer *ib;
5238
5239     TRACE("(%p) : MinVtxIdx %u, NumVIdx %u, index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u\n",
5240             This, MinVertexIndex, NumVertices, index_count, pIndexData,
5241             IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5242
5243     if(!This->stateBlock->vertexDecl) {
5244         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5245         return WINED3DERR_INVALIDCALL;
5246     }
5247
5248     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
5249         idxStride = 2;
5250     } else {
5251         idxStride = 4;
5252     }
5253
5254     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5255     vb = This->stateBlock->streamSource[0];
5256     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
5257     if (vb) IWineD3DBuffer_Release(vb);
5258     This->stateBlock->streamIsUP = TRUE;
5259     This->stateBlock->streamOffset[0] = 0;
5260     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5261
5262     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5263     This->stateBlock->baseVertexIndex = 0;
5264     This->stateBlock->loadBaseVertexIndex = 0;
5265     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5266     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5267     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5268
5269     drawPrimitive(iface, index_count, NumVertices, 0 /* start_idx */,
5270             idxStride, pIndexData, MinVertexIndex);
5271
5272     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5273     This->stateBlock->streamSource[0] = NULL;
5274     This->stateBlock->streamStride[0] = 0;
5275     ib = This->stateBlock->pIndexData;
5276     if(ib) {
5277         IWineD3DBuffer_Release(ib);
5278         This->stateBlock->pIndexData = NULL;
5279     }
5280     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5281      * SetStreamSource to specify a vertex buffer
5282      */
5283
5284     return WINED3D_OK;
5285 }
5286
5287 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
5288         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
5289 {
5290     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5291
5292     /* Mark the state dirty until we have nicer tracking
5293      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5294      * that value.
5295      */
5296     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5297     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5298     This->stateBlock->baseVertexIndex = 0;
5299     This->up_strided = DrawPrimStrideData;
5300     drawPrimitive(iface, vertex_count, 0, 0, 0, NULL, 0);
5301     This->up_strided = NULL;
5302     return WINED3D_OK;
5303 }
5304
5305 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
5306         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
5307         UINT NumVertices, const void *pIndexData, WINED3DFORMAT IndexDataFormat)
5308 {
5309     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5310     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
5311
5312     /* Mark the state dirty until we have nicer tracking
5313      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5314      * that value.
5315      */
5316     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5317     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5318     This->stateBlock->streamIsUP = TRUE;
5319     This->stateBlock->baseVertexIndex = 0;
5320     This->up_strided = DrawPrimStrideData;
5321     drawPrimitive(iface, vertex_count, 0 /* numindices */, 0 /* start_idx */, idxSize, pIndexData, 0 /* minindex */);
5322     This->up_strided = NULL;
5323     return WINED3D_OK;
5324 }
5325
5326 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
5327     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5328      * not callable by the app directly no parameter validation checks are needed here.
5329      */
5330     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5331     WINED3DLOCKED_BOX src;
5332     WINED3DLOCKED_BOX dst;
5333     HRESULT hr;
5334     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
5335
5336     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5337      * dirtification to improve loading performance.
5338      */
5339     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
5340     if(FAILED(hr)) return hr;
5341     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
5342     if(FAILED(hr)) {
5343     IWineD3DVolume_UnlockBox(pSourceVolume);
5344             return hr;
5345     }
5346
5347     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
5348
5349     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
5350     if(FAILED(hr)) {
5351         IWineD3DVolume_UnlockBox(pSourceVolume);
5352     } else {
5353         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
5354     }
5355     return hr;
5356 }
5357
5358 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5359 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5360     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5361     HRESULT hr = WINED3D_OK;
5362     WINED3DRESOURCETYPE sourceType;
5363     WINED3DRESOURCETYPE destinationType;
5364     int i ,levels;
5365
5366     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5367
5368     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5369
5370     /* verify that the source and destination textures aren't NULL */
5371     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5372         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5373              This, pSourceTexture, pDestinationTexture);
5374         hr = WINED3DERR_INVALIDCALL;
5375     }
5376
5377     if (pSourceTexture == pDestinationTexture) {
5378         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5379              This, pSourceTexture, pDestinationTexture);
5380         hr = WINED3DERR_INVALIDCALL;
5381     }
5382     /* Verify that the source and destination textures are the same type */
5383     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5384     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5385
5386     if (sourceType != destinationType) {
5387         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5388              This);
5389         hr = WINED3DERR_INVALIDCALL;
5390     }
5391
5392     /* check that both textures have the identical numbers of levels  */
5393     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5394         WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5395         hr = WINED3DERR_INVALIDCALL;
5396     }
5397
5398     if (WINED3D_OK == hr) {
5399         IWineD3DBaseTextureImpl *pDestImpl = (IWineD3DBaseTextureImpl *) pDestinationTexture;
5400
5401         /* Make sure that the destination texture is loaded */
5402         pDestImpl->baseTexture.internal_preload(pDestinationTexture, SRGB_RGB);
5403
5404         /* Update every surface level of the texture */
5405         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5406
5407         switch (sourceType) {
5408         case WINED3DRTYPE_TEXTURE:
5409             {
5410                 IWineD3DSurface *srcSurface;
5411                 IWineD3DSurface *destSurface;
5412
5413                 for (i = 0 ; i < levels ; ++i) {
5414                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5415                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5416                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5417                     IWineD3DSurface_Release(srcSurface);
5418                     IWineD3DSurface_Release(destSurface);
5419                     if (WINED3D_OK != hr) {
5420                         WARN("(%p) : Call to update surface failed\n", This);
5421                         return hr;
5422                     }
5423                 }
5424             }
5425             break;
5426         case WINED3DRTYPE_CUBETEXTURE:
5427             {
5428                 IWineD3DSurface *srcSurface;
5429                 IWineD3DSurface *destSurface;
5430                 WINED3DCUBEMAP_FACES faceType;
5431
5432                 for (i = 0 ; i < levels ; ++i) {
5433                     /* Update each cube face */
5434                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5435                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5436                         if (WINED3D_OK != hr) {
5437                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5438                         } else {
5439                             TRACE("Got srcSurface %p\n", srcSurface);
5440                         }
5441                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5442                         if (WINED3D_OK != hr) {
5443                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5444                         } else {
5445                             TRACE("Got desrSurface %p\n", destSurface);
5446                         }
5447                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5448                         IWineD3DSurface_Release(srcSurface);
5449                         IWineD3DSurface_Release(destSurface);
5450                         if (WINED3D_OK != hr) {
5451                             WARN("(%p) : Call to update surface failed\n", This);
5452                             return hr;
5453                         }
5454                     }
5455                 }
5456             }
5457             break;
5458
5459         case WINED3DRTYPE_VOLUMETEXTURE:
5460             {
5461                 IWineD3DVolume  *srcVolume  = NULL;
5462                 IWineD3DVolume  *destVolume = NULL;
5463
5464                 for (i = 0 ; i < levels ; ++i) {
5465                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5466                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5467                     hr =  IWineD3DDeviceImpl_UpdateVolume(iface, srcVolume, destVolume);
5468                     IWineD3DVolume_Release(srcVolume);
5469                     IWineD3DVolume_Release(destVolume);
5470                     if (WINED3D_OK != hr) {
5471                         WARN("(%p) : Call to update volume failed\n", This);
5472                         return hr;
5473                     }
5474                 }
5475             }
5476             break;
5477
5478         default:
5479             FIXME("(%p) : Unsupported source and destination type\n", This);
5480             hr = WINED3DERR_INVALIDCALL;
5481         }
5482     }
5483
5484     return hr;
5485 }
5486
5487 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5488     IWineD3DSwapChain *swapChain;
5489     HRESULT hr;
5490     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5491     if(hr == WINED3D_OK) {
5492         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5493                 IWineD3DSwapChain_Release(swapChain);
5494     }
5495     return hr;
5496 }
5497
5498 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5499     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5500     IWineD3DBaseTextureImpl *texture;
5501     DWORD i;
5502
5503     TRACE("(%p) : %p\n", This, pNumPasses);
5504
5505     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5506         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) {
5507             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5508             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5509         }
5510         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) {
5511             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5512             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5513         }
5514
5515         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5516         if (!texture || texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5517
5518         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) {
5519             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5520             return E_FAIL;
5521         }
5522         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) {
5523             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5524             return E_FAIL;
5525         }
5526         if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE &&
5527            This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) {
5528             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5529             return E_FAIL;
5530         }
5531     }
5532
5533     /* return a sensible default */
5534     *pNumPasses = 1;
5535
5536     TRACE("returning D3D_OK\n");
5537     return WINED3D_OK;
5538 }
5539
5540 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5541 {
5542     int i;
5543
5544     for (i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5545             IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5546             if (texture && (texture->resource.format_desc->format == WINED3DFMT_P8
5547                     || texture->resource.format_desc->format == WINED3DFMT_A8P8))
5548             {
5549                 IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5550             }
5551         }
5552 }
5553
5554 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5555     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5556     int j;
5557     UINT NewSize;
5558     PALETTEENTRY **palettes;
5559
5560     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5561
5562     if (PaletteNumber >= MAX_PALETTES) {
5563         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5564         return WINED3DERR_INVALIDCALL;
5565     }
5566
5567     if (PaletteNumber >= This->NumberOfPalettes) {
5568         NewSize = This->NumberOfPalettes;
5569         do {
5570            NewSize *= 2;
5571         } while(PaletteNumber >= NewSize);
5572         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5573         if (!palettes) {
5574             ERR("Out of memory!\n");
5575             return E_OUTOFMEMORY;
5576         }
5577         This->palettes = palettes;
5578         This->NumberOfPalettes = NewSize;
5579     }
5580
5581     if (!This->palettes[PaletteNumber]) {
5582         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5583         if (!This->palettes[PaletteNumber]) {
5584             ERR("Out of memory!\n");
5585             return E_OUTOFMEMORY;
5586         }
5587     }
5588
5589     for (j = 0; j < 256; ++j) {
5590         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5591         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5592         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5593         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5594     }
5595     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5596     TRACE("(%p) : returning\n", This);
5597     return WINED3D_OK;
5598 }
5599
5600 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5602     int j;
5603     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5604     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5605         /* What happens in such situation isn't documented; Native seems to silently abort
5606            on such conditions. Return Invalid Call. */
5607         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5608         return WINED3DERR_INVALIDCALL;
5609     }
5610     for (j = 0; j < 256; ++j) {
5611         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5612         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5613         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5614         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5615     }
5616     TRACE("(%p) : returning\n", This);
5617     return WINED3D_OK;
5618 }
5619
5620 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5621     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5622     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5623     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5624        (tested with reference rasterizer). Return Invalid Call. */
5625     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5626         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5627         return WINED3DERR_INVALIDCALL;
5628     }
5629     /*TODO: stateblocks */
5630     if (This->currentPalette != PaletteNumber) {
5631         This->currentPalette = PaletteNumber;
5632         dirtify_p8_texture_samplers(This);
5633     }
5634     TRACE("(%p) : returning\n", This);
5635     return WINED3D_OK;
5636 }
5637
5638 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5640     if (PaletteNumber == NULL) {
5641         WARN("(%p) : returning Invalid Call\n", This);
5642         return WINED3DERR_INVALIDCALL;
5643     }
5644     /*TODO: stateblocks */
5645     *PaletteNumber = This->currentPalette;
5646     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5647     return WINED3D_OK;
5648 }
5649
5650 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5651     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5652     static BOOL warned;
5653     if (!warned)
5654     {
5655         FIXME("(%p) : stub\n", This);
5656         warned = TRUE;
5657     }
5658
5659     This->softwareVertexProcessing = bSoftware;
5660     return WINED3D_OK;
5661 }
5662
5663
5664 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5665     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5666     static BOOL warned;
5667     if (!warned)
5668     {
5669         FIXME("(%p) : stub\n", This);
5670         warned = TRUE;
5671     }
5672     return This->softwareVertexProcessing;
5673 }
5674
5675
5676 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5677     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5678     IWineD3DSwapChain *swapChain;
5679     HRESULT hr;
5680
5681     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5682
5683     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5684     if(hr == WINED3D_OK){
5685         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5686         IWineD3DSwapChain_Release(swapChain);
5687     }else{
5688         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5689     }
5690     return hr;
5691 }
5692
5693
5694 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5695     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5696     static BOOL warned;
5697     if(nSegments != 0.0f) {
5698         if (!warned)
5699         {
5700             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5701             warned = TRUE;
5702         }
5703     }
5704     return WINED3D_OK;
5705 }
5706
5707 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5708     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5709     static BOOL warned;
5710     if (!warned)
5711     {
5712         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5713         warned = TRUE;
5714     }
5715     return 0.0f;
5716 }
5717
5718 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5719     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5720     /** TODO: remove casts to IWineD3DSurfaceImpl
5721      *       NOTE: move code to surface to accomplish this
5722       ****************************************/
5723     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5724     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)pDestinationSurface;
5725     int srcWidth, srcHeight;
5726     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5727     WINED3DFORMAT destFormat, srcFormat;
5728     UINT          destSize;
5729     int srcLeft, destLeft, destTop;
5730     WINED3DPOOL       srcPool, destPool;
5731     int offset    = 0;
5732     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5733     const struct GlPixelFormatDesc *src_format_desc, *dst_format_desc;
5734     GLenum dummy;
5735     DWORD sampler;
5736     int bpp;
5737     CONVERT_TYPES convert = NO_CONVERSION;
5738
5739     WINED3DSURFACE_DESC  winedesc;
5740
5741     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5742
5743     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5744     srcSurfaceWidth = winedesc.width;
5745     srcSurfaceHeight = winedesc.height;
5746     srcPool = winedesc.pool;
5747     srcFormat = winedesc.format;
5748
5749     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5750     destSurfaceWidth = winedesc.width;
5751     destSurfaceHeight = winedesc.height;
5752     destPool = winedesc.pool;
5753     destFormat = winedesc.format;
5754     destSize = winedesc.size;
5755
5756     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5757         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5758         return WINED3DERR_INVALIDCALL;
5759     }
5760
5761     /* This call loads the opengl surface directly, instead of copying the surface to the
5762      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5763      * copy in sysmem and use regular surface loading.
5764      */
5765     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5766     if(convert != NO_CONVERSION) {
5767         return IWineD3DSurface_BltFast(pDestinationSurface,
5768                                         pDestPoint  ? pDestPoint->x : 0,
5769                                         pDestPoint  ? pDestPoint->y : 0,
5770                                         pSourceSurface, pSourceRect, 0);
5771     }
5772
5773     if (destFormat == WINED3DFMT_UNKNOWN) {
5774         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5775         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5776
5777         /* Get the update surface description */
5778         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5779     }
5780
5781     ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
5782
5783     ENTER_GL();
5784     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5785     checkGLcall("glActiveTextureARB");
5786     LEAVE_GL();
5787
5788     /* Make sure the surface is loaded and up to date */
5789     surface_internal_preload(pDestinationSurface, SRGB_RGB);
5790     IWineD3DSurface_BindTexture(pDestinationSurface, FALSE);
5791
5792     src_format_desc = ((IWineD3DSurfaceImpl *)pSrcSurface)->resource.format_desc;
5793     dst_format_desc = dst_impl->resource.format_desc;
5794
5795     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5796     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5797     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5798     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5799     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5800     destTop    = pDestPoint  ? pDestPoint->y : 0;
5801
5802
5803     /* This function doesn't support compressed textures
5804     the pitch is just bytesPerPixel * width */
5805     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5806         rowoffset = srcSurfaceWidth * src_format_desc->byte_count;
5807         offset   += srcLeft * src_format_desc->byte_count;
5808         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5809     }
5810     /* TODO DXT formats */
5811
5812     if(pSourceRect != NULL && pSourceRect->top != 0){
5813        offset +=  pSourceRect->top * srcSurfaceWidth * src_format_desc->byte_count;
5814     }
5815     TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n",
5816             This, dst_impl->texture_level, destLeft, destTop, srcWidth, srcHeight, dst_format_desc->glFormat,
5817             dst_format_desc->glType, IWineD3DSurface_GetData(pSourceSurface), offset);
5818
5819     /* Sanity check */
5820     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5821
5822         /* need to lock the surface to get the data */
5823         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5824     }
5825
5826     ENTER_GL();
5827
5828     /* TODO: Cube and volume support */
5829     if(rowoffset != 0){
5830         /* not a whole row so we have to do it a line at a time */
5831         int j;
5832
5833         /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5834         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5835
5836         for (j = destTop; j < (srcHeight + destTop); ++j)
5837         {
5838             glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, j,
5839                     srcWidth, 1, dst_format_desc->glFormat, dst_format_desc->glType,data);
5840             data += rowoffset;
5841         }
5842
5843     } else { /* Full width, so just write out the whole texture */
5844         const unsigned char* data = ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5845
5846         if (dst_format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
5847         {
5848             if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth)
5849             {
5850                 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */
5851                 FIXME("Updating part of a compressed texture is not supported.\n");
5852             }
5853             if (destFormat != srcFormat)
5854             {
5855                 FIXME("Updating mixed format compressed textures is not supported.\n");
5856             }
5857             else
5858             {
5859                 GL_EXTCALL(glCompressedTexImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5860                         dst_format_desc->glInternal, srcWidth, srcHeight, 0, destSize, data));
5861             }
5862         }
5863         else
5864         {
5865             glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, destLeft, destTop,
5866                     srcWidth, srcHeight, dst_format_desc->glFormat, dst_format_desc->glType, data);
5867         }
5868      }
5869     checkGLcall("glTexSubImage2D");
5870
5871     LEAVE_GL();
5872
5873     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5874     sampler = This->rev_tex_unit_map[0];
5875     if (sampler != WINED3D_UNMAPPED_STAGE)
5876     {
5877         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5878     }
5879
5880     return WINED3D_OK;
5881 }
5882
5883 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5884     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5885     struct WineD3DRectPatch *patch;
5886     GLenum old_primitive_type;
5887     unsigned int i;
5888     struct list *e;
5889     BOOL found;
5890     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5891
5892     if(!(Handle || pRectPatchInfo)) {
5893         /* TODO: Write a test for the return value, thus the FIXME */
5894         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5895         return WINED3DERR_INVALIDCALL;
5896     }
5897
5898     if(Handle) {
5899         i = PATCHMAP_HASHFUNC(Handle);
5900         found = FALSE;
5901         LIST_FOR_EACH(e, &This->patches[i]) {
5902             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5903             if(patch->Handle == Handle) {
5904                 found = TRUE;
5905                 break;
5906             }
5907         }
5908
5909         if(!found) {
5910             TRACE("Patch does not exist. Creating a new one\n");
5911             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5912             patch->Handle = Handle;
5913             list_add_head(&This->patches[i], &patch->entry);
5914         } else {
5915             TRACE("Found existing patch %p\n", patch);
5916         }
5917     } else {
5918         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5919          * attributes we have to tesselate, read back, and draw. This needs a patch
5920          * management structure instance. Create one.
5921          *
5922          * A possible improvement is to check if a vertex shader is used, and if not directly
5923          * draw the patch.
5924          */
5925         FIXME("Drawing an uncached patch. This is slow\n");
5926         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5927     }
5928
5929     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5930        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5931        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5932         HRESULT hr;
5933         TRACE("Tesselation density or patch info changed, retesselating\n");
5934
5935         if(pRectPatchInfo) {
5936             patch->RectPatchInfo = *pRectPatchInfo;
5937         }
5938         patch->numSegs[0] = pNumSegs[0];
5939         patch->numSegs[1] = pNumSegs[1];
5940         patch->numSegs[2] = pNumSegs[2];
5941         patch->numSegs[3] = pNumSegs[3];
5942
5943         hr = tesselate_rectpatch(This, patch);
5944         if(FAILED(hr)) {
5945             WARN("Patch tesselation failed\n");
5946
5947             /* Do not release the handle to store the params of the patch */
5948             if(!Handle) {
5949                 HeapFree(GetProcessHeap(), 0, patch);
5950             }
5951             return hr;
5952         }
5953     }
5954
5955     This->currentPatch = patch;
5956     old_primitive_type = This->stateBlock->gl_primitive_type;
5957     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5958     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5959     This->stateBlock->gl_primitive_type = old_primitive_type;
5960     This->currentPatch = NULL;
5961
5962     /* Destroy uncached patches */
5963     if(!Handle) {
5964         HeapFree(GetProcessHeap(), 0, patch->mem);
5965         HeapFree(GetProcessHeap(), 0, patch);
5966     }
5967     return WINED3D_OK;
5968 }
5969
5970 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5971     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5972     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5973     FIXME("(%p) : Stub\n", This);
5974     return WINED3D_OK;
5975 }
5976
5977 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5978     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5979     int i;
5980     struct WineD3DRectPatch *patch;
5981     struct list *e;
5982     TRACE("(%p) Handle(%d)\n", This, Handle);
5983
5984     i = PATCHMAP_HASHFUNC(Handle);
5985     LIST_FOR_EACH(e, &This->patches[i]) {
5986         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5987         if(patch->Handle == Handle) {
5988             TRACE("Deleting patch %p\n", patch);
5989             list_remove(&patch->entry);
5990             HeapFree(GetProcessHeap(), 0, patch->mem);
5991             HeapFree(GetProcessHeap(), 0, patch);
5992             return WINED3D_OK;
5993         }
5994     }
5995
5996     /* TODO: Write a test for the return value */
5997     FIXME("Attempt to destroy nonexistent patch\n");
5998     return WINED3DERR_INVALIDCALL;
5999 }
6000
6001 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
6002     HRESULT hr;
6003     IWineD3DSwapChain *swapchain;
6004
6005     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
6006     if (SUCCEEDED(hr)) {
6007         IWineD3DSwapChain_Release((IUnknown *)swapchain);
6008         return swapchain;
6009     }
6010
6011     return NULL;
6012 }
6013
6014 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface,
6015         const WINED3DRECT *rect, const float color[4])
6016 {
6017     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6018     struct wined3d_context *context;
6019     IWineD3DSwapChain *swapchain;
6020
6021     swapchain = get_swapchain(surface);
6022     if (swapchain) {
6023         GLenum buffer;
6024
6025         TRACE("Surface %p is onscreen\n", surface);
6026
6027         context = ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD);
6028         ENTER_GL();
6029         context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL);
6030         buffer = surface_get_gl_buffer(surface, swapchain);
6031         glDrawBuffer(buffer);
6032         checkGLcall("glDrawBuffer()");
6033     } else {
6034         TRACE("Surface %p is offscreen\n", surface);
6035
6036         context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6037         ENTER_GL();
6038         context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->dst_fbo);
6039         context_attach_surface_fbo(context, GL_FRAMEBUFFER_EXT, 0, surface);
6040         context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER_EXT, NULL, FALSE);
6041     }
6042
6043     if (rect) {
6044         glEnable(GL_SCISSOR_TEST);
6045         if(!swapchain) {
6046             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
6047         } else {
6048             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
6049                     rect->x2 - rect->x1, rect->y2 - rect->y1);
6050         }
6051         checkGLcall("glScissor");
6052         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
6053     } else {
6054         glDisable(GL_SCISSOR_TEST);
6055     }
6056     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6057
6058     glDisable(GL_BLEND);
6059     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE));
6060
6061     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6062     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
6063
6064     glClearColor(color[0], color[1], color[2], color[3]);
6065     glClear(GL_COLOR_BUFFER_BIT);
6066     checkGLcall("glClear");
6067
6068     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
6069             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
6070         glDrawBuffer(GL_BACK);
6071         checkGLcall("glDrawBuffer()");
6072     }
6073
6074     LEAVE_GL();
6075 }
6076
6077 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
6078     unsigned int r, g, b, a;
6079     DWORD ret;
6080
6081     if(destfmt == WINED3DFMT_A8R8G8B8 || destfmt == WINED3DFMT_X8R8G8B8 ||
6082        destfmt == WINED3DFMT_R8G8B8)
6083         return color;
6084
6085     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
6086
6087     a = (color & 0xff000000) >> 24;
6088     r = (color & 0x00ff0000) >> 16;
6089     g = (color & 0x0000ff00) >>  8;
6090     b = (color & 0x000000ff) >>  0;
6091
6092     switch(destfmt)
6093     {
6094         case WINED3DFMT_R5G6B5:
6095             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
6096             r = (r * 32) / 256;
6097             g = (g * 64) / 256;
6098             b = (b * 32) / 256;
6099             ret  = r << 11;
6100             ret |= g << 5;
6101             ret |= b;
6102             TRACE("Returning %08x\n", ret);
6103             return ret;
6104
6105         case WINED3DFMT_X1R5G5B5:
6106         case WINED3DFMT_A1R5G5B5:
6107             a = (a *  2) / 256;
6108             r = (r * 32) / 256;
6109             g = (g * 32) / 256;
6110             b = (b * 32) / 256;
6111             ret  = a << 15;
6112             ret |= r << 10;
6113             ret |= g <<  5;
6114             ret |= b <<  0;
6115             TRACE("Returning %08x\n", ret);
6116             return ret;
6117
6118         case WINED3DFMT_A8_UNORM:
6119             TRACE("Returning %08x\n", a);
6120             return a;
6121
6122         case WINED3DFMT_X4R4G4B4:
6123         case WINED3DFMT_A4R4G4B4:
6124             a = (a * 16) / 256;
6125             r = (r * 16) / 256;
6126             g = (g * 16) / 256;
6127             b = (b * 16) / 256;
6128             ret  = a << 12;
6129             ret |= r <<  8;
6130             ret |= g <<  4;
6131             ret |= b <<  0;
6132             TRACE("Returning %08x\n", ret);
6133             return ret;
6134
6135         case WINED3DFMT_R3G3B2:
6136             r = (r * 8) / 256;
6137             g = (g * 8) / 256;
6138             b = (b * 4) / 256;
6139             ret  = r <<  5;
6140             ret |= g <<  2;
6141             ret |= b <<  0;
6142             TRACE("Returning %08x\n", ret);
6143             return ret;
6144
6145         case WINED3DFMT_X8B8G8R8:
6146         case WINED3DFMT_R8G8B8A8_UNORM:
6147             ret  = a << 24;
6148             ret |= b << 16;
6149             ret |= g <<  8;
6150             ret |= r <<  0;
6151             TRACE("Returning %08x\n", ret);
6152             return ret;
6153
6154         case WINED3DFMT_A2R10G10B10:
6155             a = (a *    4) / 256;
6156             r = (r * 1024) / 256;
6157             g = (g * 1024) / 256;
6158             b = (b * 1024) / 256;
6159             ret  = a << 30;
6160             ret |= r << 20;
6161             ret |= g << 10;
6162             ret |= b <<  0;
6163             TRACE("Returning %08x\n", ret);
6164             return ret;
6165
6166         case WINED3DFMT_R10G10B10A2_UNORM:
6167             a = (a *    4) / 256;
6168             r = (r * 1024) / 256;
6169             g = (g * 1024) / 256;
6170             b = (b * 1024) / 256;
6171             ret  = a << 30;
6172             ret |= b << 20;
6173             ret |= g << 10;
6174             ret |= r <<  0;
6175             TRACE("Returning %08x\n", ret);
6176             return ret;
6177
6178         default:
6179             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
6180             return 0;
6181     }
6182 }
6183
6184 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6185     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6186     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6187     WINEDDBLTFX BltFx;
6188     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
6189
6190     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6191         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6192         return WINED3DERR_INVALIDCALL;
6193     }
6194
6195     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6196         const float c[4] = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)};
6197         color_fill_fbo(iface, pSurface, pRect, c);
6198         return WINED3D_OK;
6199     } else {
6200         /* Just forward this to the DirectDraw blitting engine */
6201         memset(&BltFx, 0, sizeof(BltFx));
6202         BltFx.dwSize = sizeof(BltFx);
6203         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format_desc->format);
6204         return IWineD3DSurface_Blt(pSurface, (const RECT *)pRect, NULL, NULL,
6205                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
6206     }
6207 }
6208
6209 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
6210         IWineD3DRendertargetView *rendertarget_view, const float color[4])
6211 {
6212     IWineD3DResource *resource;
6213     IWineD3DSurface *surface;
6214     HRESULT hr;
6215
6216     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
6217     if (FAILED(hr))
6218     {
6219         ERR("Failed to get resource, hr %#x\n", hr);
6220         return;
6221     }
6222
6223     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
6224     {
6225         FIXME("Only supported on surface resources\n");
6226         IWineD3DResource_Release(resource);
6227         return;
6228     }
6229
6230     surface = (IWineD3DSurface *)resource;
6231
6232     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
6233     {
6234         color_fill_fbo(iface, surface, NULL, color);
6235     }
6236     else
6237     {
6238         WINEDDBLTFX BltFx;
6239         WINED3DCOLOR c;
6240
6241         WARN("Converting to WINED3DCOLOR, this might give incorrect results\n");
6242
6243         c = ((DWORD)(color[2] * 255.0f));
6244         c |= ((DWORD)(color[1] * 255.0f)) << 8;
6245         c |= ((DWORD)(color[0] * 255.0f)) << 16;
6246         c |= ((DWORD)(color[3] * 255.0f)) << 24;
6247
6248         /* Just forward this to the DirectDraw blitting engine */
6249         memset(&BltFx, 0, sizeof(BltFx));
6250         BltFx.dwSize = sizeof(BltFx);
6251         BltFx.u5.dwFillColor = argb_to_fmt(c, ((IWineD3DSurfaceImpl *)surface)->resource.format_desc->format);
6252         hr = IWineD3DSurface_Blt(surface, NULL, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
6253         if (FAILED(hr))
6254         {
6255             ERR("Blt failed, hr %#x\n", hr);
6256         }
6257     }
6258
6259     IWineD3DResource_Release(resource);
6260 }
6261
6262 /* rendertarget and depth stencil functions */
6263 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6264     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6265
6266     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6267         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
6268         return WINED3DERR_INVALIDCALL;
6269     }
6270
6271     *ppRenderTarget = This->render_targets[RenderTargetIndex];
6272     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6273     /* Note inc ref on returned surface */
6274     if(*ppRenderTarget != NULL)
6275         IWineD3DSurface_AddRef(*ppRenderTarget);
6276     return WINED3D_OK;
6277 }
6278
6279 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6280     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6281     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6282     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6283     IWineD3DSwapChainImpl *Swapchain;
6284     HRESULT hr;
6285
6286     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6287
6288     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6289     if(hr != WINED3D_OK) {
6290         ERR("Can't get the swapchain\n");
6291         return hr;
6292     }
6293
6294     /* Make sure to release the swapchain */
6295     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6296
6297     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6298         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6299         return WINED3DERR_INVALIDCALL;
6300     }
6301     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6302         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6303         return WINED3DERR_INVALIDCALL;
6304     }
6305
6306     if(Swapchain->frontBuffer != Front) {
6307         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6308
6309         if(Swapchain->frontBuffer)
6310         {
6311             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6312             ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags &= ~SFLAG_SWAPCHAIN;
6313         }
6314         Swapchain->frontBuffer = Front;
6315
6316         if(Swapchain->frontBuffer) {
6317             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6318             ((IWineD3DSurfaceImpl *)Swapchain->frontBuffer)->Flags |= SFLAG_SWAPCHAIN;
6319         }
6320     }
6321
6322     if(Back && !Swapchain->backBuffer) {
6323         /* We need memory for the back buffer array - only one back buffer this way */
6324         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6325         if(!Swapchain->backBuffer) {
6326             ERR("Out of memory\n");
6327             return E_OUTOFMEMORY;
6328         }
6329     }
6330
6331     if(Swapchain->backBuffer[0] != Back) {
6332         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6333
6334         /* What to do about the context here in the case of multithreading? Not sure.
6335          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6336          */
6337         WARN("No active context?\n");
6338
6339         ENTER_GL();
6340         if(!Swapchain->backBuffer[0]) {
6341             /* GL was told to draw to the front buffer at creation,
6342              * undo that
6343              */
6344             glDrawBuffer(GL_BACK);
6345             checkGLcall("glDrawBuffer(GL_BACK)");
6346             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6347             Swapchain->presentParms.BackBufferCount = 1;
6348         } else if (!Back) {
6349             /* That makes problems - disable for now */
6350             /* glDrawBuffer(GL_FRONT); */
6351             checkGLcall("glDrawBuffer(GL_FRONT)");
6352             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6353             Swapchain->presentParms.BackBufferCount = 0;
6354         }
6355         LEAVE_GL();
6356
6357         if(Swapchain->backBuffer[0])
6358         {
6359             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6360             ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags &= ~SFLAG_SWAPCHAIN;
6361         }
6362         Swapchain->backBuffer[0] = Back;
6363
6364         if(Swapchain->backBuffer[0]) {
6365             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6366             ((IWineD3DSurfaceImpl *)Swapchain->backBuffer[0])->Flags |= SFLAG_SWAPCHAIN;
6367         } else {
6368             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6369             Swapchain->backBuffer = NULL;
6370         }
6371
6372     }
6373
6374     return WINED3D_OK;
6375 }
6376
6377 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6378     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6379     *ppZStencilSurface = This->stencilBufferTarget;
6380     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6381
6382     if(*ppZStencilSurface != NULL) {
6383         /* Note inc ref on returned surface */
6384         IWineD3DSurface_AddRef(*ppZStencilSurface);
6385         return WINED3D_OK;
6386     } else {
6387         return WINED3DERR_NOTFOUND;
6388     }
6389 }
6390
6391 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6392         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip)
6393 {
6394     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6395     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6396     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6397     struct wined3d_context *context;
6398     GLenum gl_filter;
6399     POINT offset = {0, 0};
6400
6401     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6402             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6403     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6404     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6405
6406     switch (filter) {
6407         case WINED3DTEXF_LINEAR:
6408             gl_filter = GL_LINEAR;
6409             break;
6410
6411         default:
6412             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6413         case WINED3DTEXF_NONE:
6414         case WINED3DTEXF_POINT:
6415             gl_filter = GL_NEAREST;
6416             break;
6417     }
6418
6419     /* Attach src surface to src fbo */
6420     src_swapchain = get_swapchain(src_surface);
6421     dst_swapchain = get_swapchain(dst_surface);
6422
6423     if (src_swapchain) context = ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6424     else if (dst_swapchain) context = ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6425     else context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6426
6427     if (src_swapchain) {
6428         GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6429
6430         TRACE("Source surface %p is onscreen\n", src_surface);
6431         /* Make sure the drawable is up to date. In the offscreen case
6432          * attach_surface_fbo() implicitly takes care of this. */
6433         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
6434
6435         if(buffer == GL_FRONT) {
6436             RECT windowsize;
6437             UINT h;
6438             ClientToScreen(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &offset);
6439             GetClientRect(((IWineD3DSwapChainImpl *)src_swapchain)->win_handle, &windowsize);
6440             h = windowsize.bottom - windowsize.top;
6441             src_rect->x1 -= offset.x; src_rect->x2 -=offset.x;
6442             src_rect->y1 =  offset.y + h - src_rect->y1;
6443             src_rect->y2 =  offset.y + h - src_rect->y2;
6444         } else {
6445             src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6446             src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6447         }
6448
6449         ENTER_GL();
6450         context_bind_fbo(context, GL_READ_FRAMEBUFFER_EXT, NULL);
6451         glReadBuffer(buffer);
6452         checkGLcall("glReadBuffer()");
6453     } else {
6454         TRACE("Source surface %p is offscreen\n", src_surface);
6455         ENTER_GL();
6456         context_bind_fbo(context, GL_READ_FRAMEBUFFER_EXT, &context->src_fbo);
6457         context_attach_surface_fbo(context, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
6458         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
6459         checkGLcall("glReadBuffer()");
6460         context_attach_depth_stencil_fbo(context, GL_READ_FRAMEBUFFER_EXT, NULL, FALSE);
6461     }
6462     LEAVE_GL();
6463
6464     /* Attach dst surface to dst fbo */
6465     if (dst_swapchain) {
6466         GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6467
6468         TRACE("Destination surface %p is onscreen\n", dst_surface);
6469         /* Make sure the drawable is up to date. In the offscreen case
6470          * attach_surface_fbo() implicitly takes care of this. */
6471         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
6472
6473         if(buffer == GL_FRONT) {
6474             RECT windowsize;
6475             UINT h;
6476             ClientToScreen(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &offset);
6477             GetClientRect(((IWineD3DSwapChainImpl *)dst_swapchain)->win_handle, &windowsize);
6478             h = windowsize.bottom - windowsize.top;
6479             dst_rect->x1 -= offset.x; dst_rect->x2 -=offset.x;
6480             dst_rect->y1 =  offset.y + h - dst_rect->y1;
6481             dst_rect->y2 =  offset.y + h - dst_rect->y2;
6482         } else {
6483             /* Screen coords = window coords, surface height = window height */
6484             dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6485             dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6486         }
6487
6488         ENTER_GL();
6489         context_bind_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, NULL);
6490         glDrawBuffer(buffer);
6491         checkGLcall("glDrawBuffer()");
6492     } else {
6493         TRACE("Destination surface %p is offscreen\n", dst_surface);
6494
6495         ENTER_GL();
6496         context_bind_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, &context->dst_fbo);
6497         context_attach_surface_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
6498         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
6499         checkGLcall("glDrawBuffer()");
6500         context_attach_depth_stencil_fbo(context, GL_DRAW_FRAMEBUFFER_EXT, NULL, FALSE);
6501     }
6502     glDisable(GL_SCISSOR_TEST);
6503     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6504
6505     if (flip) {
6506         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6507                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
6508         checkGLcall("glBlitFramebuffer()");
6509     } else {
6510         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6511                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
6512         checkGLcall("glBlitFramebuffer()");
6513     }
6514
6515     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
6516
6517     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6518     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6519             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6520         glDrawBuffer(GL_BACK);
6521         checkGLcall("glDrawBuffer()");
6522     }
6523     LEAVE_GL();
6524 }
6525
6526 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6527     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6528     WINED3DVIEWPORT viewport;
6529
6530     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6531
6532     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6533         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6534              This, RenderTargetIndex, GL_LIMITS(buffers));
6535         return WINED3DERR_INVALIDCALL;
6536     }
6537
6538     /* MSDN says that null disables the render target
6539     but a device must always be associated with a render target
6540     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6541     */
6542     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6543         FIXME("Trying to set render target 0 to NULL\n");
6544         return WINED3DERR_INVALIDCALL;
6545     }
6546     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6547         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);
6548         return WINED3DERR_INVALIDCALL;
6549     }
6550
6551     /* If we are trying to set what we already have, don't bother */
6552     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6553         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6554         return WINED3D_OK;
6555     }
6556     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6557     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6558     This->render_targets[RenderTargetIndex] = pRenderTarget;
6559
6560     /* Render target 0 is special */
6561     if(RenderTargetIndex == 0) {
6562         /* Finally, reset the viewport as the MSDN states. */
6563         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6564         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6565         viewport.X      = 0;
6566         viewport.Y      = 0;
6567         viewport.MaxZ   = 1.0f;
6568         viewport.MinZ   = 0.0f;
6569         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6570     }
6571     return WINED3D_OK;
6572 }
6573
6574 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6575     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6576     HRESULT  hr = WINED3D_OK;
6577     IWineD3DSurface *tmp;
6578
6579     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6580
6581     if (pNewZStencil == This->stencilBufferTarget) {
6582         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6583     } else {
6584         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6585         * depending on the renter target implementation being used.
6586         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6587         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6588         * stencil buffer and incur an extra memory overhead
6589          ******************************************************/
6590
6591         if (This->stencilBufferTarget) {
6592             if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
6593                     || ((IWineD3DSurfaceImpl *)This->stencilBufferTarget)->Flags & SFLAG_DISCARD) {
6594                 surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_DISCARDED);
6595             } else {
6596                 struct wined3d_context *context = ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
6597                 surface_load_ds_location(This->stencilBufferTarget, context, SFLAG_DS_OFFSCREEN);
6598                 surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN);
6599             }
6600         }
6601
6602         tmp = This->stencilBufferTarget;
6603         This->stencilBufferTarget = pNewZStencil;
6604         /* should we be calling the parent or the wined3d surface? */
6605         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6606         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6607         hr = WINED3D_OK;
6608
6609         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6610             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6611             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6612             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6613             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6614         }
6615     }
6616
6617     return hr;
6618 }
6619
6620 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6621                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6622     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6623     /* TODO: the use of Impl is deprecated. */
6624     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6625     WINED3DLOCKED_RECT lockedRect;
6626
6627     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6628
6629     /* some basic validation checks */
6630     if(This->cursorTexture) {
6631         ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6632         ENTER_GL();
6633         glDeleteTextures(1, &This->cursorTexture);
6634         LEAVE_GL();
6635         This->cursorTexture = 0;
6636     }
6637
6638     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6639         This->haveHardwareCursor = TRUE;
6640     else
6641         This->haveHardwareCursor = FALSE;
6642
6643     if(pCursorBitmap) {
6644         WINED3DLOCKED_RECT rect;
6645
6646         /* MSDN: Cursor must be A8R8G8B8 */
6647         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format_desc->format)
6648         {
6649             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6650             return WINED3DERR_INVALIDCALL;
6651         }
6652
6653         /* MSDN: Cursor must be smaller than the display mode */
6654         if(pSur->currentDesc.Width > This->ddraw_width ||
6655            pSur->currentDesc.Height > This->ddraw_height) {
6656             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);
6657             return WINED3DERR_INVALIDCALL;
6658         }
6659
6660         if (!This->haveHardwareCursor) {
6661             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6662
6663             /* Do not store the surface's pointer because the application may
6664              * release it after setting the cursor image. Windows doesn't
6665              * addref the set surface, so we can't do this either without
6666              * creating circular refcount dependencies. Copy out the gl texture
6667              * instead.
6668              */
6669             This->cursorWidth = pSur->currentDesc.Width;
6670             This->cursorHeight = pSur->currentDesc.Height;
6671             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6672             {
6673                 const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION);
6674                 char *mem, *bits = rect.pBits;
6675                 GLint intfmt = glDesc->glInternal;
6676                 GLint format = glDesc->glFormat;
6677                 GLint type = glDesc->glType;
6678                 INT height = This->cursorHeight;
6679                 INT width = This->cursorWidth;
6680                 INT bpp = glDesc->byte_count;
6681                 DWORD sampler;
6682                 INT i;
6683
6684                 /* Reformat the texture memory (pitch and width can be
6685                  * different) */
6686                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6687                 for(i = 0; i < height; i++)
6688                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6689                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6690
6691                 ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
6692
6693                 ENTER_GL();
6694
6695                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6696                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6697                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6698                 }
6699
6700                 /* Make sure that a proper texture unit is selected */
6701                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6702                 checkGLcall("glActiveTextureARB");
6703                 sampler = This->rev_tex_unit_map[0];
6704                 if (sampler != WINED3D_UNMAPPED_STAGE)
6705                 {
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 }