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