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