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