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