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