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