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