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