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