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