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