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