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