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