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