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