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