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