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