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