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