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