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