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