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