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