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