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