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