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