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