wined3d: Rename the "format" field in wined3d_format_desc to "id".
[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->id), debug_d3ddeclusage(element->usage));
278                 stride_used = FALSE;
279             }
280             else
281             {
282                 stride_used = fixed_get_input(element->usage, element->usage_idx, &idx);
283             }
284         }
285
286         if (stride_used)
287         {
288             TRACE("Load %s array %u [usage %s, usage_idx %u, "
289                     "input_slot %u, offset %u, stride %u, format %s, buffer_object %u]\n",
290                     use_vshader ? "shader": "fixed function", idx,
291                     debug_d3ddeclusage(element->usage), element->usage_idx, element->input_slot,
292                     element->offset, stride, debug_d3dformat(element->format_desc->id), 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->id == WINED3DFMT_B8G8R8A8_UNORM)
302             {
303                 stream_info->swizzle_map |= 1 << idx;
304             }
305             stream_info->use_map |= 1 << idx;
306         }
307     }
308
309     This->num_buffer_queries = 0;
310     if (!This->stateBlock->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->id == WINED3DFMT_B8G8R8A8_UNORM)
385         {
386             stream_info->swizzle_map |= 1 << i;
387         }
388         stream_info->use_map |= 1 << i;
389     }
390 }
391
392 static void device_trace_strided_stream_info(const struct wined3d_stream_info *stream_info)
393 {
394     TRACE("Strided Data:\n");
395     TRACE_STRIDED(stream_info, WINED3D_FFP_POSITION);
396     TRACE_STRIDED(stream_info, WINED3D_FFP_BLENDWEIGHT);
397     TRACE_STRIDED(stream_info, WINED3D_FFP_BLENDINDICES);
398     TRACE_STRIDED(stream_info, WINED3D_FFP_NORMAL);
399     TRACE_STRIDED(stream_info, WINED3D_FFP_PSIZE);
400     TRACE_STRIDED(stream_info, WINED3D_FFP_DIFFUSE);
401     TRACE_STRIDED(stream_info, WINED3D_FFP_SPECULAR);
402     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD0);
403     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD1);
404     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD2);
405     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD3);
406     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD4);
407     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD5);
408     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD6);
409     TRACE_STRIDED(stream_info, WINED3D_FFP_TEXCOORD7);
410 }
411
412 /* Context activation is done by the caller. */
413 void device_update_stream_info(IWineD3DDeviceImpl *device, const struct wined3d_gl_info *gl_info)
414 {
415     struct wined3d_stream_info *stream_info = &device->strided_streams;
416     IWineD3DStateBlockImpl *stateblock = device->stateBlock;
417     BOOL vs = stateblock->vertexShader && device->vs_selected_mode != SHADER_NONE;
418     BOOL fixup = FALSE;
419
420     if (device->up_strided)
421     {
422         /* Note: this is a ddraw fixed-function code path. */
423         TRACE("=============================== Strided Input ================================\n");
424         device_stream_info_from_strided(gl_info, device->up_strided, stream_info);
425         if (TRACE_ON(d3d)) device_trace_strided_stream_info(stream_info);
426     }
427     else
428     {
429         TRACE("============================= Vertex Declaration =============================\n");
430         device_stream_info_from_declaration(device, vs, stream_info, &fixup);
431     }
432
433     if (vs && !stream_info->position_transformed)
434     {
435         if (((IWineD3DVertexDeclarationImpl *)stateblock->vertexDecl)->half_float_conv_needed && !fixup)
436         {
437             TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion.\n");
438             device->useDrawStridedSlow = TRUE;
439         }
440         else
441         {
442             device->useDrawStridedSlow = FALSE;
443         }
444     }
445     else
446     {
447         WORD slow_mask = (1 << WINED3D_FFP_PSIZE);
448         slow_mask |= -!gl_info->supported[ARB_VERTEX_ARRAY_BGRA]
449                 & ((1 << WINED3D_FFP_DIFFUSE) | (1 << WINED3D_FFP_SPECULAR));
450
451         if ((stream_info->position_transformed || (stream_info->use_map & slow_mask)) && !fixup)
452         {
453             device->useDrawStridedSlow = TRUE;
454         }
455         else
456         {
457             device->useDrawStridedSlow = FALSE;
458         }
459     }
460 }
461
462 static void device_preload_texture(IWineD3DStateBlockImpl *stateblock, unsigned int idx)
463 {
464     IWineD3DBaseTextureImpl *texture;
465     enum WINED3DSRGB srgb;
466
467     if (!(texture = (IWineD3DBaseTextureImpl *)stateblock->textures[idx])) return;
468     srgb = stateblock->samplerState[idx][WINED3DSAMP_SRGBTEXTURE] ? SRGB_SRGB : SRGB_RGB;
469     texture->baseTexture.internal_preload((IWineD3DBaseTexture *)texture, srgb);
470 }
471
472 void device_preload_textures(IWineD3DDeviceImpl *device)
473 {
474     IWineD3DStateBlockImpl *stateblock = device->stateBlock;
475     unsigned int i;
476
477     if (use_vs(stateblock))
478     {
479         for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i)
480         {
481             if (((IWineD3DBaseShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.sampler_type[i])
482                 device_preload_texture(stateblock, MAX_FRAGMENT_SAMPLERS + i);
483         }
484     }
485
486     if (use_ps(stateblock))
487     {
488         for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
489         {
490             if (((IWineD3DBaseShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.sampler_type[i])
491                 device_preload_texture(stateblock, i);
492         }
493     }
494     else
495     {
496         WORD ffu_map = device->fixed_function_usage_map;
497
498         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
499         {
500             if (ffu_map & 1)
501                 device_preload_texture(stateblock, i);
502         }
503     }
504 }
505
506 BOOL device_context_add(IWineD3DDeviceImpl *device, struct wined3d_context *context)
507 {
508     struct wined3d_context **new_array;
509
510     TRACE("Adding context %p.\n", context);
511
512     if (!device->contexts) new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_array));
513     else new_array = HeapReAlloc(GetProcessHeap(), 0, device->contexts, sizeof(*new_array) * (device->numContexts + 1));
514
515     if (!new_array)
516     {
517         ERR("Failed to grow the context array.\n");
518         return FALSE;
519     }
520
521     new_array[device->numContexts++] = context;
522     device->contexts = new_array;
523     return TRUE;
524 }
525
526 void device_context_remove(IWineD3DDeviceImpl *device, struct wined3d_context *context)
527 {
528     struct wined3d_context **new_array;
529     BOOL found = FALSE;
530     UINT i;
531
532     TRACE("Removing context %p.\n", context);
533
534     for (i = 0; i < device->numContexts; ++i)
535     {
536         if (device->contexts[i] == context)
537         {
538             found = TRUE;
539             break;
540         }
541     }
542
543     if (!found)
544     {
545         ERR("Context %p doesn't exist in context array.\n", context);
546         return;
547     }
548
549     if (!--device->numContexts)
550     {
551         HeapFree(GetProcessHeap(), 0, device->contexts);
552         device->contexts = NULL;
553         return;
554     }
555
556     memmove(&device->contexts[i], &device->contexts[i + 1], (device->numContexts - i) * sizeof(*device->contexts));
557     new_array = HeapReAlloc(GetProcessHeap(), 0, device->contexts, device->numContexts * sizeof(*device->contexts));
558     if (!new_array)
559     {
560         ERR("Failed to shrink context array. Oh well.\n");
561         return;
562     }
563
564     device->contexts = new_array;
565 }
566
567 void device_get_draw_rect(IWineD3DDeviceImpl *device, RECT *rect)
568 {
569     IWineD3DStateBlockImpl *stateblock = device->stateBlock;
570     WINED3DVIEWPORT *vp = &stateblock->viewport;
571
572     SetRect(rect, vp->X, vp->Y, vp->X + vp->Width, vp->Y + vp->Height);
573
574     if (stateblock->renderState[WINED3DRS_SCISSORTESTENABLE])
575     {
576         IntersectRect(rect, rect, &stateblock->scissorRect);
577     }
578 }
579
580 void device_switch_onscreen_ds(IWineD3DDeviceImpl *device,
581         struct wined3d_context *context, IWineD3DSurfaceImpl *depth_stencil)
582 {
583     if (device->onscreen_depth_stencil)
584     {
585         surface_load_ds_location(device->onscreen_depth_stencil, context, SFLAG_DS_OFFSCREEN);
586         surface_modify_ds_location(device->onscreen_depth_stencil, SFLAG_DS_OFFSCREEN,
587                 device->onscreen_depth_stencil->ds_current_size.cx,
588                 device->onscreen_depth_stencil->ds_current_size.cy);
589         IWineD3DSurface_Release((IWineD3DSurface *)device->onscreen_depth_stencil);
590     }
591     device->onscreen_depth_stencil = depth_stencil;
592     IWineD3DSurface_AddRef((IWineD3DSurface *)device->onscreen_depth_stencil);
593 }
594
595 static BOOL is_full_clear(IWineD3DSurfaceImpl *target, const RECT *draw_rect, const RECT *clear_rect)
596 {
597     /* partial draw rect */
598     if (draw_rect->left || draw_rect->top
599             || draw_rect->right < target->currentDesc.Width
600             || draw_rect->bottom < target->currentDesc.Height)
601         return FALSE;
602
603     /* partial clear rect */
604     if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0
605             || clear_rect->right < target->currentDesc.Width
606             || clear_rect->bottom < target->currentDesc.Height))
607         return FALSE;
608
609     return TRUE;
610 }
611
612 static void prepare_ds_clear(IWineD3DSurfaceImpl *ds, struct wined3d_context *context,
613         DWORD location, const RECT *draw_rect, UINT rect_count, const RECT *clear_rect)
614 {
615     RECT current_rect, r;
616
617     if (ds->Flags & location)
618         SetRect(&current_rect, 0, 0,
619                 ds->ds_current_size.cx,
620                 ds->ds_current_size.cy);
621     else
622         SetRectEmpty(&current_rect);
623
624     IntersectRect(&r, draw_rect, &current_rect);
625     if (EqualRect(&r, draw_rect))
626     {
627         /* current_rect âŠ‡ draw_rect, modify only. */
628         surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy);
629         return;
630     }
631
632     if (EqualRect(&r, &current_rect))
633     {
634         /* draw_rect âŠ‡ current_rect, test if we're doing a full clear. */
635
636         if (!clear_rect)
637         {
638             /* Full clear, modify only. */
639             surface_modify_ds_location(ds, location, draw_rect->right, draw_rect->bottom);
640             return;
641         }
642
643         IntersectRect(&r, draw_rect, clear_rect);
644         if (EqualRect(&r, draw_rect))
645         {
646             /* clear_rect âŠ‡ draw_rect, modify only. */
647             surface_modify_ds_location(ds, location, draw_rect->right, draw_rect->bottom);
648             return;
649         }
650     }
651
652     /* Full load. */
653     surface_load_ds_location(ds, context, location);
654     surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy);
655 }
656
657 HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, IWineD3DSurfaceImpl **rts,
658         UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags,
659         const WINED3DCOLORVALUE *color, float depth, DWORD stencil)
660 {
661     const RECT *clear_rect = (rect_count > 0 && rects) ? (const RECT *)rects : NULL;
662     IWineD3DSurfaceImpl *depth_stencil = device->depth_stencil;
663     IWineD3DSurfaceImpl *target = rts[0];
664     UINT drawable_width, drawable_height;
665     struct wined3d_context *context;
666     GLbitfield clear_mask = 0;
667     unsigned int i;
668
669     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
670      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
671      * for the cleared parts, and the untouched parts.
672      *
673      * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
674      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
675      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
676      * checking all this if the dest surface is in the drawable anyway. */
677     if (flags & WINED3DCLEAR_TARGET && !is_full_clear(target, draw_rect, clear_rect))
678     {
679         for (i = 0; i < rt_count; ++i)
680         {
681             if (rts[i]) surface_load_location(rts[i], SFLAG_INDRAWABLE, NULL);
682         }
683     }
684
685     context = context_acquire(device, target);
686     if (!context->valid)
687     {
688         context_release(context);
689         WARN("Invalid context, skipping clear.\n");
690         return WINED3D_OK;
691     }
692
693     context_apply_clear_state(context, device, rt_count, rts, depth_stencil);
694
695     target->get_drawable_size(context, &drawable_width, &drawable_height);
696
697     ENTER_GL();
698
699     /* Only set the values up once, as they are not changing. */
700     if (flags & WINED3DCLEAR_STENCIL)
701     {
702         if (context->gl_info->supported[EXT_STENCIL_TWO_SIDE])
703         {
704             glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
705             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE));
706         }
707         glStencilMask(~0U);
708         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
709         glClearStencil(stencil);
710         checkGLcall("glClearStencil");
711         clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
712     }
713
714     if (flags & WINED3DCLEAR_ZBUFFER)
715     {
716         DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
717
718         if (location == SFLAG_DS_ONSCREEN && depth_stencil != device->onscreen_depth_stencil)
719             device_switch_onscreen_ds(device, context, depth_stencil);
720         prepare_ds_clear(depth_stencil, context, location, draw_rect, rect_count, clear_rect);
721         surface_modify_location(depth_stencil, SFLAG_INDRAWABLE, TRUE);
722
723         glDepthMask(GL_TRUE);
724         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
725         glClearDepth(depth);
726         checkGLcall("glClearDepth");
727         clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
728     }
729
730     if (flags & WINED3DCLEAR_TARGET)
731     {
732         for (i = 0; i < rt_count; ++i)
733         {
734             if (rts[i]) surface_modify_location(rts[i], SFLAG_INDRAWABLE, TRUE);
735         }
736
737         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
738         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
739         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
740         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
741         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
742         glClearColor(color->r, color->g, color->b, color->a);
743         checkGLcall("glClearColor");
744         clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
745     }
746
747     if (!clear_rect)
748     {
749         if (context->render_offscreen)
750         {
751             glScissor(draw_rect->left, draw_rect->top,
752                     draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
753         }
754         else
755         {
756             glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
757                         draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
758         }
759         checkGLcall("glScissor");
760         glClear(clear_mask);
761         checkGLcall("glClear");
762     }
763     else
764     {
765         RECT current_rect;
766
767         /* Now process each rect in turn. */
768         for (i = 0; i < rect_count; ++i)
769         {
770             /* Note that GL uses lower left, width/height. */
771             IntersectRect(&current_rect, draw_rect, &clear_rect[i]);
772
773             TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
774                     wine_dbgstr_rect(&clear_rect[i]),
775                     wine_dbgstr_rect(&current_rect));
776
777             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
778              * The rectangle is not cleared, no error is returned, but further rectanlges are
779              * still cleared if they are valid. */
780             if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
781             {
782                 TRACE("Rectangle with negative dimensions, ignoring.\n");
783                 continue;
784             }
785
786             if (context->render_offscreen)
787             {
788                 glScissor(current_rect.left, current_rect.top,
789                         current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
790             }
791             else
792             {
793                 glScissor(current_rect.left, drawable_height - current_rect.bottom,
794                           current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
795             }
796             checkGLcall("glScissor");
797
798             glClear(clear_mask);
799             checkGLcall("glClear");
800         }
801     }
802
803     LEAVE_GL();
804
805     if (wined3d_settings.strict_draw_ordering || (target->container.type == WINED3D_CONTAINER_SWAPCHAIN
806             && target->container.u.swapchain->front_buffer == target))
807         wglFlush(); /* Flush to ensure ordering across contexts. */
808
809     context_release(context);
810
811     return WINED3D_OK;
812 }
813
814
815 /**********************************************************
816  * IUnknown parts follows
817  **********************************************************/
818
819 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
820 {
821     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
822
823     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
824     if (IsEqualGUID(riid, &IID_IUnknown)
825         || IsEqualGUID(riid, &IID_IWineD3DBase)
826         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
827         IUnknown_AddRef(iface);
828         *ppobj = This;
829         return S_OK;
830     }
831     *ppobj = NULL;
832     return E_NOINTERFACE;
833 }
834
835 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
836     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
837     ULONG refCount = InterlockedIncrement(&This->ref);
838
839     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
840     return refCount;
841 }
842
843 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
844     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
845     ULONG refCount = InterlockedDecrement(&This->ref);
846
847     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
848
849     if (!refCount) {
850         UINT i;
851
852         for (i = 0; i < sizeof(This->multistate_funcs)/sizeof(This->multistate_funcs[0]); ++i) {
853             HeapFree(GetProcessHeap(), 0, This->multistate_funcs[i]);
854             This->multistate_funcs[i] = NULL;
855         }
856
857         /* TODO: Clean up all the surfaces and textures! */
858         /* NOTE: You must release the parent if the object was created via a callback
859         ** ***************************/
860
861         if (!list_empty(&This->resources))
862         {
863             IWineD3DResourceImpl *resource;
864             FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
865
866             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry)
867             {
868                 WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource);
869                 FIXME("Leftover resource %p with type %s (%#x).\n",
870                         resource, debug_d3dresourcetype(type), type);
871             }
872         }
873
874         if(This->contexts) ERR("Context array not freed!\n");
875         if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
876         This->haveHardwareCursor = FALSE;
877
878         IWineD3D_Release(This->wined3d);
879         This->wined3d = NULL;
880         HeapFree(GetProcessHeap(), 0, This);
881         TRACE("Freed device  %p\n", This);
882         This = NULL;
883     }
884     return refCount;
885 }
886
887 /**********************************************************
888  * IWineD3DDevice implementation follows
889  **********************************************************/
890 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
891     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
892     *pParent = This->parent;
893     IUnknown_AddRef(This->parent);
894     return WINED3D_OK;
895 }
896
897 static HRESULT WINAPI IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice *iface, struct wined3d_buffer_desc *desc,
898         const void *data, IUnknown *parent, const struct wined3d_parent_ops *parent_ops, IWineD3DBuffer **buffer)
899 {
900     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
901     struct wined3d_buffer *object;
902     HRESULT hr;
903
904     TRACE("iface %p, desc %p, data %p, parent %p, buffer %p\n", iface, desc, data, parent, buffer);
905
906     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
907     if (!object)
908     {
909         ERR("Failed to allocate memory\n");
910         return E_OUTOFMEMORY;
911     }
912
913     FIXME("Ignoring access flags (pool)\n");
914
915     hr = buffer_init(object, This, desc->byte_width, desc->usage, WINED3DFMT_UNKNOWN,
916             WINED3DPOOL_MANAGED, GL_ARRAY_BUFFER_ARB, data, parent, parent_ops);
917     if (FAILED(hr))
918     {
919         WARN("Failed to initialize buffer, hr %#x.\n", hr);
920         HeapFree(GetProcessHeap(), 0, object);
921         return hr;
922     }
923     object->desc = *desc;
924
925     TRACE("Created buffer %p.\n", object);
926
927     *buffer = (IWineD3DBuffer *)object;
928
929     return WINED3D_OK;
930 }
931
932 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface,
933         UINT Size, DWORD Usage, WINED3DPOOL Pool, IWineD3DBuffer **ppVertexBuffer,
934         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
935 {
936     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
937     struct wined3d_buffer *object;
938     HRESULT hr;
939
940     TRACE("iface %p, size %u, usage %#x, pool %#x, buffer %p, parent %p, parent_ops %p.\n",
941             iface, Size, Usage, Pool, ppVertexBuffer, parent, parent_ops);
942
943     if (Pool == WINED3DPOOL_SCRATCH)
944     {
945         /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
946          * anyway, SCRATCH vertex buffers aren't usable anywhere
947          */
948         WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
949         *ppVertexBuffer = NULL;
950         return WINED3DERR_INVALIDCALL;
951     }
952
953     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
954     if (!object)
955     {
956         ERR("Out of memory\n");
957         *ppVertexBuffer = NULL;
958         return WINED3DERR_OUTOFVIDEOMEMORY;
959     }
960
961     hr = buffer_init(object, This, Size, Usage, WINED3DFMT_VERTEXDATA,
962             Pool, GL_ARRAY_BUFFER_ARB, NULL, parent, parent_ops);
963     if (FAILED(hr))
964     {
965         WARN("Failed to initialize buffer, hr %#x.\n", hr);
966         HeapFree(GetProcessHeap(), 0, object);
967         return hr;
968     }
969
970     TRACE("Created buffer %p.\n", object);
971     *ppVertexBuffer = (IWineD3DBuffer *)object;
972
973     return WINED3D_OK;
974 }
975
976 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface,
977         UINT Length, DWORD Usage, WINED3DPOOL Pool, IWineD3DBuffer **ppIndexBuffer,
978         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
979 {
980     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
981     struct wined3d_buffer *object;
982     HRESULT hr;
983
984     TRACE("(%p) Creating index buffer\n", This);
985
986     /* Allocate the storage for the device */
987     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
988     if (!object)
989     {
990         ERR("Out of memory\n");
991         *ppIndexBuffer = NULL;
992         return WINED3DERR_OUTOFVIDEOMEMORY;
993     }
994
995     hr = buffer_init(object, This, Length, Usage | WINED3DUSAGE_STATICDECL,
996             WINED3DFMT_UNKNOWN, Pool, GL_ELEMENT_ARRAY_BUFFER_ARB, NULL,
997             parent, parent_ops);
998     if (FAILED(hr))
999     {
1000         WARN("Failed to initialize buffer, hr %#x\n", hr);
1001         HeapFree(GetProcessHeap(), 0, object);
1002         return hr;
1003     }
1004
1005     TRACE("Created buffer %p.\n", object);
1006
1007     *ppIndexBuffer = (IWineD3DBuffer *) object;
1008
1009     return WINED3D_OK;
1010 }
1011
1012 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice *iface,
1013         WINED3DSTATEBLOCKTYPE type, IWineD3DStateBlock **stateblock)
1014 {
1015     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1016     IWineD3DStateBlockImpl *object;
1017     HRESULT hr;
1018
1019     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1020     if(!object)
1021     {
1022         ERR("Failed to allocate stateblock memory.\n");
1023         return E_OUTOFMEMORY;
1024     }
1025
1026     hr = stateblock_init(object, This, type);
1027     if (FAILED(hr))
1028     {
1029         WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1030         HeapFree(GetProcessHeap(), 0, object);
1031         return hr;
1032     }
1033
1034     TRACE("Created stateblock %p.\n", object);
1035     *stateblock = (IWineD3DStateBlock *)object;
1036
1037     return WINED3D_OK;
1038 }
1039
1040 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height,
1041         enum wined3d_format_id Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **surface,
1042         DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
1043         WINED3DSURFTYPE Impl, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1044 {
1045     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1046     IWineD3DSurfaceImpl *object;
1047     HRESULT hr;
1048
1049     TRACE("iface %p, width %u, height %u, format %s (%#x), lockable %#x, discard %#x, level %u\n",
1050             iface, Width, Height, debug_d3dformat(Format), Format, Lockable, Discard, Level);
1051     TRACE("surface %p, usage %s (%#x), pool %s (%#x), multisample_type %#x, multisample_quality %u\n",
1052             surface, debug_d3dusage(Usage), Usage, debug_d3dpool(Pool), Pool, MultiSample, MultisampleQuality);
1053     TRACE("surface_type %#x, parent %p, parent_ops %p.\n", Impl, parent, parent_ops);
1054
1055     if (Impl == SURFACE_OPENGL && !This->adapter)
1056     {
1057         ERR("OpenGL surfaces are not available without OpenGL.\n");
1058         return WINED3DERR_NOTAVAILABLE;
1059     }
1060
1061     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1062     if (!object)
1063     {
1064         ERR("Failed to allocate surface memory.\n");
1065         return WINED3DERR_OUTOFVIDEOMEMORY;
1066     }
1067
1068     hr = surface_init(object, Impl, This->surface_alignment, Width, Height, Level, Lockable,
1069             Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent, parent_ops);
1070     if (FAILED(hr))
1071     {
1072         WARN("Failed to initialize surface, returning %#x.\n", hr);
1073         HeapFree(GetProcessHeap(), 0, object);
1074         return hr;
1075     }
1076
1077     TRACE("(%p) : Created surface %p\n", This, object);
1078
1079     *surface = (IWineD3DSurface *)object;
1080
1081     return hr;
1082 }
1083
1084 static HRESULT WINAPI IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice *iface,
1085         IWineD3DResource *resource, IUnknown *parent, IWineD3DRendertargetView **rendertarget_view)
1086 {
1087     struct wined3d_rendertarget_view *object;
1088
1089     TRACE("iface %p, resource %p, parent %p, rendertarget_view %p.\n",
1090             iface, resource, parent, rendertarget_view);
1091
1092     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1093     if (!object)
1094     {
1095         ERR("Failed to allocate memory\n");
1096         return E_OUTOFMEMORY;
1097     }
1098
1099     wined3d_rendertarget_view_init(object, resource, parent);
1100
1101     TRACE("Created render target view %p.\n", object);
1102     *rendertarget_view = (IWineD3DRendertargetView *)object;
1103
1104     return WINED3D_OK;
1105 }
1106
1107 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
1108         UINT Width, UINT Height, UINT Levels, DWORD Usage, enum wined3d_format_id Format, WINED3DPOOL Pool,
1109         IWineD3DTexture **ppTexture, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1110 {
1111     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1112     IWineD3DTextureImpl *object;
1113     HRESULT hr;
1114
1115     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
1116     TRACE("Format %#x (%s), Pool %#x, ppTexture %p, parent %p\n",
1117             Format, debug_d3dformat(Format), Pool, ppTexture, parent);
1118
1119     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1120     if (!object)
1121     {
1122         ERR("Out of memory\n");
1123         *ppTexture = NULL;
1124         return WINED3DERR_OUTOFVIDEOMEMORY;
1125     }
1126
1127     hr = texture_init(object, Width, Height, Levels, This, Usage, Format, Pool, parent, parent_ops);
1128     if (FAILED(hr))
1129     {
1130         WARN("Failed to initialize texture, returning %#x\n", hr);
1131         HeapFree(GetProcessHeap(), 0, object);
1132         *ppTexture = NULL;
1133         return hr;
1134     }
1135
1136     *ppTexture = (IWineD3DTexture *)object;
1137
1138     TRACE("(%p) : Created texture %p\n", This, object);
1139
1140     return WINED3D_OK;
1141 }
1142
1143 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1144         UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, enum wined3d_format_id Format, WINED3DPOOL Pool,
1145         IWineD3DVolumeTexture **ppVolumeTexture, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1146 {
1147     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
1148     IWineD3DVolumeTextureImpl *object;
1149     HRESULT hr;
1150
1151     TRACE("(%p) : W(%u) H(%u) D(%u), Lvl(%u) Usage(%#x), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1152           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1153
1154     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1155     if (!object)
1156     {
1157         ERR("Out of memory\n");
1158         *ppVolumeTexture = NULL;
1159         return WINED3DERR_OUTOFVIDEOMEMORY;
1160     }
1161
1162     hr = volumetexture_init(object, Width, Height, Depth, Levels, This, Usage, Format, Pool, parent, parent_ops);
1163     if (FAILED(hr))
1164     {
1165         WARN("Failed to initialize volumetexture, returning %#x\n", hr);
1166         HeapFree(GetProcessHeap(), 0, object);
1167         *ppVolumeTexture = NULL;
1168         return hr;
1169     }
1170
1171     TRACE("(%p) : Created volume texture %p.\n", This, object);
1172     *ppVolumeTexture = (IWineD3DVolumeTexture *)object;
1173
1174     return WINED3D_OK;
1175 }
1176
1177 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, UINT Width, UINT Height,
1178         UINT Depth, DWORD Usage, enum wined3d_format_id Format, WINED3DPOOL Pool, IWineD3DVolume **ppVolume,
1179         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1180 {
1181     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1182     IWineD3DVolumeImpl *object;
1183     HRESULT hr;
1184
1185     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1186           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1187
1188     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1189     if (!object)
1190     {
1191         ERR("Out of memory\n");
1192         *ppVolume = NULL;
1193         return WINED3DERR_OUTOFVIDEOMEMORY;
1194     }
1195
1196     hr = volume_init(object, This, Width, Height, Depth, Usage, Format, Pool, parent, parent_ops);
1197     if (FAILED(hr))
1198     {
1199         WARN("Failed to initialize volume, returning %#x.\n", hr);
1200         HeapFree(GetProcessHeap(), 0, object);
1201         return hr;
1202     }
1203
1204     TRACE("(%p) : Created volume %p.\n", This, object);
1205     *ppVolume = (IWineD3DVolume *)object;
1206
1207     return WINED3D_OK;
1208 }
1209
1210 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength, UINT Levels,
1211         DWORD Usage, enum wined3d_format_id Format, WINED3DPOOL Pool, IWineD3DCubeTexture **ppCubeTexture,
1212         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1213 {
1214     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1215     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1216     HRESULT                  hr;
1217
1218     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1219     if (!object)
1220     {
1221         ERR("Out of memory\n");
1222         *ppCubeTexture = NULL;
1223         return WINED3DERR_OUTOFVIDEOMEMORY;
1224     }
1225
1226     hr = cubetexture_init(object, EdgeLength, Levels, This, Usage, Format, Pool, parent, parent_ops);
1227     if (FAILED(hr))
1228     {
1229         WARN("Failed to initialize cubetexture, returning %#x\n", hr);
1230         HeapFree(GetProcessHeap(), 0, object);
1231         *ppCubeTexture = NULL;
1232         return hr;
1233     }
1234
1235     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1236     *ppCubeTexture = (IWineD3DCubeTexture *)object;
1237
1238     return WINED3D_OK;
1239 }
1240
1241 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface,
1242         WINED3DQUERYTYPE type, IWineD3DQuery **query, IUnknown *parent)
1243 {
1244     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1245     IWineD3DQueryImpl *object;
1246     HRESULT hr;
1247
1248     TRACE("iface %p, type %#x, query %p, parent %p.\n", iface, type, query, parent);
1249
1250     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1251     if (!object)
1252     {
1253         ERR("Failed to allocate query memory.\n");
1254         return E_OUTOFMEMORY;
1255     }
1256
1257     hr = query_init(object, This, type, parent);
1258     if (FAILED(hr))
1259     {
1260         WARN("Failed to initialize query, hr %#x.\n", hr);
1261         HeapFree(GetProcessHeap(), 0, object);
1262         return hr;
1263     }
1264
1265     TRACE("Created query %p.\n", object);
1266     *query = (IWineD3DQuery *)object;
1267
1268     return WINED3D_OK;
1269 }
1270
1271 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
1272         WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain,
1273         IUnknown *parent, WINED3DSURFTYPE surface_type)
1274 {
1275     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1276     IWineD3DSwapChainImpl *object;
1277     HRESULT hr;
1278
1279     TRACE("iface %p, present_parameters %p, swapchain %p, parent %p, surface_type %#x.\n",
1280             iface, present_parameters, swapchain, parent, surface_type);
1281
1282     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1283     if (!object)
1284     {
1285         ERR("Failed to allocate swapchain memory.\n");
1286         return E_OUTOFMEMORY;
1287     }
1288
1289     hr = swapchain_init(object, surface_type, This, present_parameters, parent);
1290     if (FAILED(hr))
1291     {
1292         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
1293         HeapFree(GetProcessHeap(), 0, object);
1294         return hr;
1295     }
1296
1297     TRACE("Created swapchain %p.\n", object);
1298     *swapchain = (IWineD3DSwapChain *)object;
1299
1300     return WINED3D_OK;
1301 }
1302
1303 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1304 static UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1305     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1306     TRACE("(%p)\n", This);
1307
1308     return This->NumberOfSwapChains;
1309 }
1310
1311 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1313     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1314
1315     if(iSwapChain < This->NumberOfSwapChains) {
1316         *pSwapChain = This->swapchains[iSwapChain];
1317         IWineD3DSwapChain_AddRef(*pSwapChain);
1318         TRACE("(%p) returning %p\n", This, *pSwapChain);
1319         return WINED3D_OK;
1320     } else {
1321         TRACE("Swapchain out of range\n");
1322         *pSwapChain = NULL;
1323         return WINED3DERR_INVALIDCALL;
1324     }
1325 }
1326
1327 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice *iface,
1328         IWineD3DVertexDeclaration **declaration, IUnknown *parent, const struct wined3d_parent_ops *parent_ops,
1329         const WINED3DVERTEXELEMENT *elements, UINT element_count)
1330 {
1331     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1332     IWineD3DVertexDeclarationImpl *object = NULL;
1333     HRESULT hr;
1334
1335     TRACE("iface %p, declaration %p, parent %p, elements %p, element_count %u.\n",
1336             iface, declaration, parent, elements, element_count);
1337
1338     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1339     if(!object)
1340     {
1341         ERR("Failed to allocate vertex declaration memory.\n");
1342         return E_OUTOFMEMORY;
1343     }
1344
1345     hr = vertexdeclaration_init(object, This, elements, element_count, parent, parent_ops);
1346     if (FAILED(hr))
1347     {
1348         WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
1349         HeapFree(GetProcessHeap(), 0, object);
1350         return hr;
1351     }
1352
1353     TRACE("Created vertex declaration %p.\n", object);
1354     *declaration = (IWineD3DVertexDeclaration *)object;
1355
1356     return WINED3D_OK;
1357 }
1358
1359 struct wined3d_fvf_convert_state
1360 {
1361     const struct wined3d_gl_info *gl_info;
1362     WINED3DVERTEXELEMENT *elements;
1363     UINT offset;
1364     UINT idx;
1365 };
1366
1367 static void append_decl_element(struct wined3d_fvf_convert_state *state,
1368         enum wined3d_format_id format, WINED3DDECLUSAGE usage, UINT usage_idx)
1369 {
1370     WINED3DVERTEXELEMENT *elements = state->elements;
1371     const struct wined3d_format_desc *format_desc;
1372     UINT offset = state->offset;
1373     UINT idx = state->idx;
1374
1375     elements[idx].format = format;
1376     elements[idx].input_slot = 0;
1377     elements[idx].offset = offset;
1378     elements[idx].output_slot = 0;
1379     elements[idx].method = WINED3DDECLMETHOD_DEFAULT;
1380     elements[idx].usage = usage;
1381     elements[idx].usage_idx = usage_idx;
1382
1383     format_desc = getFormatDescEntry(format, state->gl_info);
1384     state->offset += format_desc->component_count * format_desc->component_size;
1385     ++state->idx;
1386 }
1387
1388 static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the GL info, which has the type table */
1389         DWORD fvf, WINED3DVERTEXELEMENT **ppVertexElements)
1390 {
1391     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
1392     BOOL has_pos = (fvf & WINED3DFVF_POSITION_MASK) != 0;
1393     BOOL has_blend = (fvf & WINED3DFVF_XYZB5) > WINED3DFVF_XYZRHW;
1394     BOOL has_blend_idx = has_blend &&
1395        (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB5) ||
1396         (fvf & WINED3DFVF_LASTBETA_D3DCOLOR) ||
1397         (fvf & WINED3DFVF_LASTBETA_UBYTE4));
1398     BOOL has_normal = (fvf & WINED3DFVF_NORMAL) != 0;
1399     BOOL has_psize = (fvf & WINED3DFVF_PSIZE) != 0;
1400     BOOL has_diffuse = (fvf & WINED3DFVF_DIFFUSE) != 0;
1401     BOOL has_specular = (fvf & WINED3DFVF_SPECULAR) !=0;
1402
1403     DWORD num_textures = (fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
1404     DWORD texcoords = (fvf & 0xFFFF0000) >> 16;
1405     struct wined3d_fvf_convert_state state;
1406     unsigned int size;
1407     unsigned int idx;
1408     DWORD num_blends = 1 + (((fvf & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
1409     if (has_blend_idx) num_blends--;
1410
1411     /* Compute declaration size */
1412     size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal +
1413            has_psize + has_diffuse + has_specular + num_textures;
1414
1415     state.gl_info = gl_info;
1416     state.elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*state.elements));
1417     if (!state.elements) return ~0U;
1418     state.offset = 0;
1419     state.idx = 0;
1420
1421     if (has_pos)
1422     {
1423         if (!has_blend && (fvf & WINED3DFVF_XYZRHW))
1424             append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_POSITIONT, 0);
1425         else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW)
1426             append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_POSITION, 0);
1427         else
1428             append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_POSITION, 0);
1429     }
1430
1431     if (has_blend && (num_blends > 0))
1432     {
1433         if ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR))
1434             append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
1435         else
1436         {
1437             switch (num_blends)
1438             {
1439                 case 1:
1440                     append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
1441                     break;
1442                 case 2:
1443                     append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
1444                     break;
1445                 case 3:
1446                     append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
1447                     break;
1448                 case 4:
1449                     append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_BLENDWEIGHT, 0);
1450                     break;
1451                 default:
1452                     ERR("Unexpected amount of blend values: %u\n", num_blends);
1453             }
1454         }
1455     }
1456
1457     if (has_blend_idx)
1458     {
1459         if ((fvf & WINED3DFVF_LASTBETA_UBYTE4)
1460                 || ((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2 && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)))
1461             append_decl_element(&state, WINED3DFMT_R8G8B8A8_UINT, WINED3DDECLUSAGE_BLENDINDICES, 0);
1462         else if (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)
1463             append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_BLENDINDICES, 0);
1464         else
1465             append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_BLENDINDICES, 0);
1466     }
1467
1468     if (has_normal) append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_NORMAL, 0);
1469     if (has_psize) append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_PSIZE, 0);
1470     if (has_diffuse) append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_COLOR, 0);
1471     if (has_specular) append_decl_element(&state, WINED3DFMT_B8G8R8A8_UNORM, WINED3DDECLUSAGE_COLOR, 1);
1472
1473     for (idx = 0; idx < num_textures; ++idx)
1474     {
1475         switch ((texcoords >> (idx * 2)) & 0x03)
1476         {
1477             case WINED3DFVF_TEXTUREFORMAT1:
1478                 append_decl_element(&state, WINED3DFMT_R32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
1479                 break;
1480             case WINED3DFVF_TEXTUREFORMAT2:
1481                 append_decl_element(&state, WINED3DFMT_R32G32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
1482                 break;
1483             case WINED3DFVF_TEXTUREFORMAT3:
1484                 append_decl_element(&state, WINED3DFMT_R32G32B32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
1485                 break;
1486             case WINED3DFVF_TEXTUREFORMAT4:
1487                 append_decl_element(&state, WINED3DFMT_R32G32B32A32_FLOAT, WINED3DDECLUSAGE_TEXCOORD, idx);
1488                 break;
1489         }
1490     }
1491
1492     *ppVertexElements = state.elements;
1493     return size;
1494 }
1495
1496 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice *iface,
1497         IWineD3DVertexDeclaration **declaration, IUnknown *parent,
1498         const struct wined3d_parent_ops *parent_ops, DWORD fvf)
1499 {
1500     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1501     WINED3DVERTEXELEMENT *elements;
1502     unsigned int size;
1503     DWORD hr;
1504
1505     TRACE("iface %p, declaration %p, parent %p, fvf %#x.\n", iface, declaration, parent, fvf);
1506
1507     size = ConvertFvfToDeclaration(This, fvf, &elements);
1508     if (size == ~0U) return E_OUTOFMEMORY;
1509
1510     hr = IWineD3DDevice_CreateVertexDeclaration(iface, declaration, parent, parent_ops, elements, size);
1511     HeapFree(GetProcessHeap(), 0, elements);
1512     return hr;
1513 }
1514
1515 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface,
1516         const DWORD *pFunction, const struct wined3d_shader_signature *output_signature,
1517         IWineD3DVertexShader **ppVertexShader, IUnknown *parent,
1518         const struct wined3d_parent_ops *parent_ops)
1519 {
1520     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1521     IWineD3DVertexShaderImpl *object;
1522     HRESULT hr;
1523
1524     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1525     if (!object)
1526     {
1527         ERR("Failed to allocate shader memory.\n");
1528         return E_OUTOFMEMORY;
1529     }
1530
1531     hr = vertexshader_init(object, This, pFunction, output_signature, parent, parent_ops);
1532     if (FAILED(hr))
1533     {
1534         WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
1535         HeapFree(GetProcessHeap(), 0, object);
1536         return hr;
1537     }
1538
1539     TRACE("Created vertex shader %p.\n", object);
1540     *ppVertexShader = (IWineD3DVertexShader *)object;
1541
1542     return WINED3D_OK;
1543 }
1544
1545 static HRESULT WINAPI IWineD3DDeviceImpl_CreateGeometryShader(IWineD3DDevice *iface,
1546         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
1547         IWineD3DGeometryShader **shader, IUnknown *parent,
1548         const struct wined3d_parent_ops *parent_ops)
1549 {
1550     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1551     struct wined3d_geometryshader *object;
1552     HRESULT hr;
1553
1554     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1555     if (!object)
1556     {
1557         ERR("Failed to allocate shader memory.\n");
1558         return E_OUTOFMEMORY;
1559     }
1560
1561     hr = geometryshader_init(object, This, byte_code, output_signature, parent, parent_ops);
1562     if (FAILED(hr))
1563     {
1564         WARN("Failed to initialize geometry shader, hr %#x.\n", hr);
1565         HeapFree(GetProcessHeap(), 0, object);
1566         return hr;
1567     }
1568
1569     TRACE("Created geometry shader %p.\n", object);
1570     *shader = (IWineD3DGeometryShader *)object;
1571
1572     return WINED3D_OK;
1573 }
1574
1575 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface,
1576         const DWORD *pFunction, const struct wined3d_shader_signature *output_signature,
1577         IWineD3DPixelShader **ppPixelShader, IUnknown *parent,
1578         const struct wined3d_parent_ops *parent_ops)
1579 {
1580     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1581     IWineD3DPixelShaderImpl *object;
1582     HRESULT hr;
1583
1584     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1585     if (!object)
1586     {
1587         ERR("Failed to allocate shader memory.\n");
1588         return E_OUTOFMEMORY;
1589     }
1590
1591     hr = pixelshader_init(object, This, pFunction, output_signature, parent, parent_ops);
1592     if (FAILED(hr))
1593     {
1594         WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
1595         HeapFree(GetProcessHeap(), 0, object);
1596         return hr;
1597     }
1598
1599     TRACE("Created pixel shader %p.\n", object);
1600     *ppPixelShader = (IWineD3DPixelShader *)object;
1601
1602     return WINED3D_OK;
1603 }
1604
1605 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags,
1606         const PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent)
1607 {
1608     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1609     IWineD3DPaletteImpl *object;
1610     HRESULT hr;
1611
1612     TRACE("iface %p, flags %#x, entries %p, palette %p, parent %p.\n",
1613             iface, Flags, PalEnt, Palette, Parent);
1614
1615     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1616     if (!object)
1617     {
1618         ERR("Failed to allocate palette memory.\n");
1619         return E_OUTOFMEMORY;
1620     }
1621
1622     hr = wined3d_palette_init(object, This, Flags, PalEnt, Parent);
1623     if (FAILED(hr))
1624     {
1625         WARN("Failed to initialize palette, hr %#x.\n", hr);
1626         HeapFree(GetProcessHeap(), 0, object);
1627         return hr;
1628     }
1629
1630     TRACE("Created palette %p.\n", object);
1631     *Palette = (IWineD3DPalette *)object;
1632
1633     return WINED3D_OK;
1634 }
1635
1636 static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *filename) {
1637     HBITMAP hbm;
1638     BITMAP bm;
1639     HRESULT hr;
1640     HDC dcb = NULL, dcs = NULL;
1641     WINEDDCOLORKEY colorkey;
1642
1643     hbm = LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
1644     if(hbm)
1645     {
1646         GetObjectA(hbm, sizeof(BITMAP), &bm);
1647         dcb = CreateCompatibleDC(NULL);
1648         if(!dcb) goto out;
1649         SelectObject(dcb, hbm);
1650     }
1651     else
1652     {
1653         /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
1654          * couldn't be loaded
1655          */
1656         memset(&bm, 0, sizeof(bm));
1657         bm.bmWidth = 32;
1658         bm.bmHeight = 32;
1659     }
1660
1661     hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *)This, bm.bmWidth, bm.bmHeight, WINED3DFMT_B5G6R5_UNORM, TRUE,
1662             FALSE, 0, &This->logo_surface, 0, WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL,
1663             NULL, &wined3d_null_parent_ops);
1664     if(FAILED(hr)) {
1665         ERR("Wine logo requested, but failed to create surface\n");
1666         goto out;
1667     }
1668
1669     if(dcb) {
1670         hr = IWineD3DSurface_GetDC(This->logo_surface, &dcs);
1671         if(FAILED(hr)) goto out;
1672         BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY);
1673         IWineD3DSurface_ReleaseDC(This->logo_surface, dcs);
1674
1675         colorkey.dwColorSpaceLowValue = 0;
1676         colorkey.dwColorSpaceHighValue = 0;
1677         IWineD3DSurface_SetColorKey(This->logo_surface, WINEDDCKEY_SRCBLT, &colorkey);
1678     }
1679     else
1680     {
1681         const WINED3DCOLORVALUE c = {1.0f, 1.0f, 1.0f, 1.0f};
1682         /* Fill the surface with a white color to show that wined3d is there */
1683         IWineD3DDevice_ColorFill((IWineD3DDevice *)This, This->logo_surface, NULL, &c);
1684     }
1685
1686 out:
1687     if (dcb) DeleteDC(dcb);
1688     if (hbm) DeleteObject(hbm);
1689 }
1690
1691 /* Context activation is done by the caller. */
1692 static void create_dummy_textures(IWineD3DDeviceImpl *This)
1693 {
1694     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
1695     unsigned int i;
1696     /* Under DirectX you can have texture stage operations even if no texture is
1697     bound, whereas opengl will only do texture operations when a valid texture is
1698     bound. We emulate this by creating dummy textures and binding them to each
1699     texture stage, but disable all stages by default. Hence if a stage is enabled
1700     then the default texture will kick in until replaced by a SetTexture call     */
1701     ENTER_GL();
1702
1703     if (gl_info->supported[APPLE_CLIENT_STORAGE])
1704     {
1705         /* The dummy texture does not have client storage backing */
1706         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
1707         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
1708     }
1709
1710     for (i = 0; i < gl_info->limits.textures; ++i)
1711     {
1712         GLubyte white = 255;
1713
1714         /* Make appropriate texture active */
1715         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
1716         checkGLcall("glActiveTextureARB");
1717
1718         /* Generate an opengl texture name */
1719         glGenTextures(1, &This->dummyTextureName[i]);
1720         checkGLcall("glGenTextures");
1721         TRACE("Dummy Texture %d given name %d\n", i, This->dummyTextureName[i]);
1722
1723         /* Generate a dummy 2d texture (not using 1d because they cause many
1724         * DRI drivers fall back to sw) */
1725         glBindTexture(GL_TEXTURE_2D, This->dummyTextureName[i]);
1726         checkGLcall("glBindTexture");
1727
1728         glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
1729         checkGLcall("glTexImage2D");
1730     }
1731
1732     if (gl_info->supported[APPLE_CLIENT_STORAGE])
1733     {
1734         /* Reenable because if supported it is enabled by default */
1735         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1736         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1737     }
1738
1739     LEAVE_GL();
1740 }
1741
1742 /* Context activation is done by the caller. */
1743 static void destroy_dummy_textures(IWineD3DDeviceImpl *device, const struct wined3d_gl_info *gl_info)
1744 {
1745     ENTER_GL();
1746     glDeleteTextures(gl_info->limits.textures, device->dummyTextureName);
1747     checkGLcall("glDeleteTextures(gl_info->limits.textures, device->dummyTextureName)");
1748     LEAVE_GL();
1749
1750     memset(device->dummyTextureName, 0, gl_info->limits.textures * sizeof(*device->dummyTextureName));
1751 }
1752
1753 static HRESULT WINAPI IWineD3DDeviceImpl_AcquireFocusWindow(IWineD3DDevice *iface, HWND window)
1754 {
1755     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
1756
1757     if (!wined3d_register_window(window, device))
1758     {
1759         ERR("Failed to register window %p.\n", window);
1760         return E_FAIL;
1761     }
1762
1763     device->focus_window = window;
1764     SetForegroundWindow(window);
1765
1766     return WINED3D_OK;
1767 }
1768
1769 static void WINAPI IWineD3DDeviceImpl_ReleaseFocusWindow(IWineD3DDevice *iface)
1770 {
1771     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
1772
1773     if (device->focus_window) wined3d_unregister_window(device->focus_window);
1774     device->focus_window = NULL;
1775 }
1776
1777 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface,
1778         WINED3DPRESENT_PARAMETERS *pPresentationParameters)
1779 {
1780     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1781     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
1782     IWineD3DSwapChainImpl *swapchain = NULL;
1783     struct wined3d_context *context;
1784     HRESULT hr;
1785     DWORD state;
1786     unsigned int i;
1787
1788     TRACE("(%p)->(%p)\n", This, pPresentationParameters);
1789
1790     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1791     if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL;
1792
1793     TRACE("(%p) : Creating stateblock\n", This);
1794     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock);
1795     if (FAILED(hr))
1796     {
1797         WARN("Failed to create stateblock\n");
1798         goto err_out;
1799     }
1800     TRACE("(%p) : Created stateblock (%p)\n", This, This->stateBlock);
1801     This->updateStateBlock = This->stateBlock;
1802     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
1803
1804     This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1805             sizeof(*This->render_targets) * gl_info->limits.buffers);
1806
1807     This->NumberOfPalettes = 1;
1808     This->palettes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PALETTEENTRY*));
1809     if (!This->palettes || !This->render_targets)
1810     {
1811         ERR("Out of memory!\n");
1812         hr = E_OUTOFMEMORY;
1813         goto err_out;
1814     }
1815     This->palettes[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256);
1816     if(!This->palettes[0]) {
1817         ERR("Out of memory!\n");
1818         hr = E_OUTOFMEMORY;
1819         goto err_out;
1820     }
1821     for (i = 0; i < 256; ++i) {
1822         This->palettes[0][i].peRed   = 0xFF;
1823         This->palettes[0][i].peGreen = 0xFF;
1824         This->palettes[0][i].peBlue  = 0xFF;
1825         This->palettes[0][i].peFlags = 0xFF;
1826     }
1827     This->currentPalette = 0;
1828
1829     /* Initialize the texture unit mapping to a 1:1 mapping */
1830     for (state = 0; state < MAX_COMBINED_SAMPLERS; ++state)
1831     {
1832         if (state < gl_info->limits.fragment_samplers)
1833         {
1834             This->texUnitMap[state] = state;
1835             This->rev_tex_unit_map[state] = state;
1836         } else {
1837             This->texUnitMap[state] = WINED3D_UNMAPPED_STAGE;
1838             This->rev_tex_unit_map[state] = WINED3D_UNMAPPED_STAGE;
1839         }
1840     }
1841
1842     /* Setup the implicit swapchain. This also initializes a context. */
1843     TRACE("Creating implicit swapchain\n");
1844     hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent,
1845             pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
1846     if (FAILED(hr))
1847     {
1848         WARN("Failed to create implicit swapchain\n");
1849         goto err_out;
1850     }
1851
1852     This->NumberOfSwapChains = 1;
1853     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1854     if(!This->swapchains) {
1855         ERR("Out of memory!\n");
1856         goto err_out;
1857     }
1858     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1859
1860     if (swapchain->back_buffers && swapchain->back_buffers[0])
1861     {
1862         TRACE("Setting rendertarget to %p.\n", swapchain->back_buffers);
1863         This->render_targets[0] = swapchain->back_buffers[0];
1864     }
1865     else
1866     {
1867         TRACE("Setting rendertarget to %p.\n", swapchain->front_buffer);
1868         This->render_targets[0] = swapchain->front_buffer;
1869     }
1870     IWineD3DSurface_AddRef((IWineD3DSurface *)This->render_targets[0]);
1871
1872     /* Depth Stencil support */
1873     This->depth_stencil = This->auto_depth_stencil;
1874     if (This->depth_stencil)
1875         IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil);
1876
1877     hr = This->shader_backend->shader_alloc_private(iface);
1878     if(FAILED(hr)) {
1879         TRACE("Shader private data couldn't be allocated\n");
1880         goto err_out;
1881     }
1882     hr = This->frag_pipe->alloc_private(iface);
1883     if(FAILED(hr)) {
1884         TRACE("Fragment pipeline private data couldn't be allocated\n");
1885         goto err_out;
1886     }
1887     hr = This->blitter->alloc_private(iface);
1888     if(FAILED(hr)) {
1889         TRACE("Blitter private data couldn't be allocated\n");
1890         goto err_out;
1891     }
1892
1893     /* Set up some starting GL setup */
1894
1895     /* Setup all the devices defaults */
1896     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, enum wined3d_format_id 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     RECT draw_rect;
4585
4586     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), color (0x%08x), Z (%f), Stencil (%d)\n", This,
4587           Count, pRects, Flags, color, Z, Stencil);
4588
4589     if (Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && !This->depth_stencil)
4590     {
4591         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4592         /* TODO: What about depth stencil buffers without stencil bits? */
4593         return WINED3DERR_INVALIDCALL;
4594     }
4595
4596     device_get_draw_rect(This, &draw_rect);
4597
4598     return device_clear_render_targets(This, This->adapter->gl_info.limits.buffers,
4599             This->render_targets, Count, (const RECT *)pRects, &draw_rect, Flags,
4600             &c, Z, Stencil);
4601 }
4602
4603 /*****
4604  * Drawing functions
4605  *****/
4606
4607 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
4608         WINED3DPRIMITIVETYPE primitive_type)
4609 {
4610     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4611
4612     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
4613
4614     This->updateStateBlock->changed.primitive_type = TRUE;
4615     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
4616 }
4617
4618 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
4619         WINED3DPRIMITIVETYPE *primitive_type)
4620 {
4621     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4622
4623     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
4624
4625     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
4626
4627     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
4628 }
4629
4630 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
4631 {
4632     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633
4634     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
4635
4636     if(!This->stateBlock->vertexDecl) {
4637         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4638         return WINED3DERR_INVALIDCALL;
4639     }
4640
4641     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4642     if(This->stateBlock->streamIsUP) {
4643         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4644         This->stateBlock->streamIsUP = FALSE;
4645     }
4646
4647     if(This->stateBlock->loadBaseVertexIndex != 0) {
4648         This->stateBlock->loadBaseVertexIndex = 0;
4649         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4650     }
4651     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4652     drawPrimitive(iface, vertex_count, StartVertex /* start_idx */, 0 /* indxSize */, NULL /* indxData */);
4653     return WINED3D_OK;
4654 }
4655
4656 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, UINT startIndex, UINT index_count)
4657 {
4658     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4659     UINT                 idxStride = 2;
4660     IWineD3DBuffer *pIB;
4661     GLuint vbo;
4662
4663     pIB = This->stateBlock->pIndexData;
4664     if (!pIB) {
4665         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4666          * without an index buffer set. (The first time at least...)
4667          * D3D8 simply dies, but I doubt it can do much harm to return
4668          * D3DERR_INVALIDCALL there as well. */
4669         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4670         return WINED3DERR_INVALIDCALL;
4671     }
4672
4673     if(!This->stateBlock->vertexDecl) {
4674         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4675         return WINED3DERR_INVALIDCALL;
4676     }
4677
4678     if(This->stateBlock->streamIsUP) {
4679         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4680         This->stateBlock->streamIsUP = FALSE;
4681     }
4682     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
4683
4684     TRACE("(%p) : startIndex %u, index count %u.\n", This, startIndex, index_count);
4685
4686     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
4687         idxStride = 2;
4688     } else {
4689         idxStride = 4;
4690     }
4691
4692     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4693         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4694         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4695     }
4696
4697     drawPrimitive(iface, index_count, startIndex, idxStride,
4698             vbo ? NULL : ((struct wined3d_buffer *)pIB)->resource.allocatedMemory);
4699
4700     return WINED3D_OK;
4701 }
4702
4703 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
4704         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4705 {
4706     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4707     IWineD3DBuffer *vb;
4708
4709     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4710             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
4711
4712     if(!This->stateBlock->vertexDecl) {
4713         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4714         return WINED3DERR_INVALIDCALL;
4715     }
4716
4717     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4718     vb = This->stateBlock->streamSource[0];
4719     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4720     if (vb) IWineD3DBuffer_Release(vb);
4721     This->stateBlock->streamOffset[0] = 0;
4722     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4723     This->stateBlock->streamIsUP = TRUE;
4724     This->stateBlock->loadBaseVertexIndex = 0;
4725
4726     /* TODO: Only mark dirty if drawing from a different UP address */
4727     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4728
4729     drawPrimitive(iface, vertex_count, 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */);
4730
4731     /* MSDN specifies stream zero settings must be set to NULL */
4732     This->stateBlock->streamStride[0] = 0;
4733     This->stateBlock->streamSource[0] = NULL;
4734
4735     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4736      * the new stream sources or use UP drawing again
4737      */
4738     return WINED3D_OK;
4739 }
4740
4741 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
4742         UINT index_count, const void *pIndexData, enum wined3d_format_id IndexDataFormat,
4743         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4744 {
4745     int                 idxStride;
4746     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4747     IWineD3DBuffer *vb;
4748     IWineD3DBuffer *ib;
4749
4750     TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4751             This, index_count, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4752
4753     if(!This->stateBlock->vertexDecl) {
4754         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4755         return WINED3DERR_INVALIDCALL;
4756     }
4757
4758     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
4759         idxStride = 2;
4760     } else {
4761         idxStride = 4;
4762     }
4763
4764     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4765     vb = This->stateBlock->streamSource[0];
4766     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4767     if (vb) IWineD3DBuffer_Release(vb);
4768     This->stateBlock->streamIsUP = TRUE;
4769     This->stateBlock->streamOffset[0] = 0;
4770     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4771
4772     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4773     This->stateBlock->baseVertexIndex = 0;
4774     This->stateBlock->loadBaseVertexIndex = 0;
4775     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4776     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4777     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4778
4779     drawPrimitive(iface, index_count, 0 /* start_idx */, idxStride, pIndexData);
4780
4781     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4782     This->stateBlock->streamSource[0] = NULL;
4783     This->stateBlock->streamStride[0] = 0;
4784     ib = This->stateBlock->pIndexData;
4785     if(ib) {
4786         IWineD3DBuffer_Release(ib);
4787         This->stateBlock->pIndexData = NULL;
4788     }
4789     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4790      * SetStreamSource to specify a vertex buffer
4791      */
4792
4793     return WINED3D_OK;
4794 }
4795
4796 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
4797         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
4798 {
4799     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4800
4801     /* Mark the state dirty until we have nicer tracking
4802      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4803      * that value.
4804      */
4805     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4806     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4807     This->stateBlock->baseVertexIndex = 0;
4808     This->up_strided = DrawPrimStrideData;
4809     drawPrimitive(iface, vertex_count, 0, 0, NULL);
4810     This->up_strided = NULL;
4811     return WINED3D_OK;
4812 }
4813
4814 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
4815         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
4816         UINT NumVertices, const void *pIndexData, enum wined3d_format_id IndexDataFormat)
4817 {
4818     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4819     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
4820
4821     /* Mark the state dirty until we have nicer tracking
4822      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4823      * that value.
4824      */
4825     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4826     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4827     This->stateBlock->streamIsUP = TRUE;
4828     This->stateBlock->baseVertexIndex = 0;
4829     This->up_strided = DrawPrimStrideData;
4830     drawPrimitive(iface, vertex_count, 0 /* start_idx */, idxSize, pIndexData);
4831     This->up_strided = NULL;
4832     return WINED3D_OK;
4833 }
4834
4835 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
4836 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface,
4837         IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume)
4838 {
4839     WINED3DLOCKED_BOX src;
4840     WINED3DLOCKED_BOX dst;
4841     HRESULT hr;
4842
4843     TRACE("iface %p, src_volume %p, dst_volume %p.\n",
4844             iface, pSourceVolume, pDestinationVolume);
4845
4846     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
4847      * dirtification to improve loading performance.
4848      */
4849     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
4850     if(FAILED(hr)) return hr;
4851     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
4852     if(FAILED(hr)) {
4853     IWineD3DVolume_UnlockBox(pSourceVolume);
4854             return hr;
4855     }
4856
4857     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
4858
4859     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
4860     if(FAILED(hr)) {
4861         IWineD3DVolume_UnlockBox(pSourceVolume);
4862     } else {
4863         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
4864     }
4865     return hr;
4866 }
4867
4868 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice *iface,
4869         IWineD3DBaseTexture *src_texture, IWineD3DBaseTexture *dst_texture)
4870 {
4871     unsigned int level_count, i;
4872     WINED3DRESOURCETYPE type;
4873     HRESULT hr;
4874
4875     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
4876
4877     /* Verify that the source and destination textures are non-NULL. */
4878     if (!src_texture || !dst_texture)
4879     {
4880         WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
4881         return WINED3DERR_INVALIDCALL;
4882     }
4883
4884     if (src_texture == dst_texture)
4885     {
4886         WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
4887         return WINED3DERR_INVALIDCALL;
4888     }
4889
4890     /* Verify that the source and destination textures are the same type. */
4891     type = IWineD3DBaseTexture_GetType(src_texture);
4892     if (IWineD3DBaseTexture_GetType(dst_texture) != type)
4893     {
4894         WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
4895         return WINED3DERR_INVALIDCALL;
4896     }
4897
4898     /* Check that both textures have the identical numbers of levels. */
4899     level_count = IWineD3DBaseTexture_GetLevelCount(src_texture);
4900     if (IWineD3DBaseTexture_GetLevelCount(dst_texture) != level_count)
4901     {
4902         WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
4903         return WINED3DERR_INVALIDCALL;
4904     }
4905
4906     /* Make sure that the destination texture is loaded. */
4907     ((IWineD3DBaseTextureImpl *)dst_texture)->baseTexture.internal_preload(dst_texture, SRGB_RGB);
4908
4909     /* Update every surface level of the texture. */
4910     switch (type)
4911     {
4912         case WINED3DRTYPE_TEXTURE:
4913         {
4914             IWineD3DSurface *src_surface;
4915             IWineD3DSurface *dst_surface;
4916
4917             for (i = 0; i < level_count; ++i)
4918             {
4919                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)src_texture, i, &src_surface);
4920                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)dst_texture, i, &dst_surface);
4921                 hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4922                 IWineD3DSurface_Release(dst_surface);
4923                 IWineD3DSurface_Release(src_surface);
4924                 if (FAILED(hr))
4925                 {
4926                     WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4927                     return hr;
4928                 }
4929             }
4930             break;
4931         }
4932
4933         case WINED3DRTYPE_CUBETEXTURE:
4934         {
4935             IWineD3DSurface *src_surface;
4936             IWineD3DSurface *dst_surface;
4937             WINED3DCUBEMAP_FACES face;
4938
4939             for (i = 0; i < level_count; ++i)
4940             {
4941                 /* Update each cube face. */
4942                 for (face = WINED3DCUBEMAP_FACE_POSITIVE_X; face <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++face)
4943                 {
4944                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)src_texture,
4945                             face, i, &src_surface);
4946                     if (FAILED(hr)) ERR("Failed to get src cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4947                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)dst_texture,
4948                             face, i, &dst_surface);
4949                     if (FAILED(hr)) ERR("Failed to get dst cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4950                     hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4951                     IWineD3DSurface_Release(dst_surface);
4952                     IWineD3DSurface_Release(src_surface);
4953                     if (FAILED(hr))
4954                     {
4955                         WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4956                         return hr;
4957                     }
4958                 }
4959             }
4960             break;
4961         }
4962
4963         case WINED3DRTYPE_VOLUMETEXTURE:
4964         {
4965             IWineD3DVolume *src_volume;
4966             IWineD3DVolume *dst_volume;
4967
4968             for (i = 0; i < level_count; ++i)
4969             {
4970                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)src_texture, i, &src_volume);
4971                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)dst_texture, i, &dst_volume);
4972                 hr = IWineD3DDeviceImpl_UpdateVolume(iface, src_volume, dst_volume);
4973                 IWineD3DVolume_Release(dst_volume);
4974                 IWineD3DVolume_Release(src_volume);
4975                 if (FAILED(hr))
4976                 {
4977                     WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr);
4978                     return hr;
4979                 }
4980             }
4981             break;
4982         }
4983
4984         default:
4985             FIXME("Unsupported texture type %#x.\n", type);
4986             return WINED3DERR_INVALIDCALL;
4987     }
4988
4989     return WINED3D_OK;
4990 }
4991
4992 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,
4993         UINT swapchain_idx, IWineD3DSurface *dst_surface)
4994 {
4995     IWineD3DSwapChain *swapchain;
4996     HRESULT hr;
4997
4998     TRACE("iface %p, swapchain_idx %u, dst_surface %p.\n", iface, swapchain_idx, dst_surface);
4999
5000     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5001     if (FAILED(hr)) return hr;
5002
5003     hr = IWineD3DSwapChain_GetFrontBufferData(swapchain, dst_surface);
5004     IWineD3DSwapChain_Release(swapchain);
5005
5006     return hr;
5007 }
5008
5009 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5010     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5011     IWineD3DBaseTextureImpl *texture;
5012     DWORD i;
5013
5014     TRACE("(%p) : %p\n", This, pNumPasses);
5015
5016     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5017         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) {
5018             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5019             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5020         }
5021         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) {
5022             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5023             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5024         }
5025
5026         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5027         if (!texture || texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5028
5029         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) {
5030             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5031             return E_FAIL;
5032         }
5033         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) {
5034             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5035             return E_FAIL;
5036         }
5037         if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE &&
5038            This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) {
5039             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5040             return E_FAIL;
5041         }
5042     }
5043
5044     /* return a sensible default */
5045     *pNumPasses = 1;
5046
5047     TRACE("returning D3D_OK\n");
5048     return WINED3D_OK;
5049 }
5050
5051 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5052 {
5053     int i;
5054
5055     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
5056     {
5057         IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5058         if (texture && (texture->resource.format_desc->id == WINED3DFMT_P8_UINT
5059                 || texture->resource.format_desc->id == WINED3DFMT_P8_UINT_A8_UNORM))
5060         {
5061             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5062         }
5063     }
5064 }
5065
5066 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5067     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5068     int j;
5069     UINT NewSize;
5070     PALETTEENTRY **palettes;
5071
5072     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5073
5074     if (PaletteNumber >= MAX_PALETTES) {
5075         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5076         return WINED3DERR_INVALIDCALL;
5077     }
5078
5079     if (PaletteNumber >= This->NumberOfPalettes) {
5080         NewSize = This->NumberOfPalettes;
5081         do {
5082            NewSize *= 2;
5083         } while(PaletteNumber >= NewSize);
5084         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5085         if (!palettes) {
5086             ERR("Out of memory!\n");
5087             return E_OUTOFMEMORY;
5088         }
5089         This->palettes = palettes;
5090         This->NumberOfPalettes = NewSize;
5091     }
5092
5093     if (!This->palettes[PaletteNumber]) {
5094         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5095         if (!This->palettes[PaletteNumber]) {
5096             ERR("Out of memory!\n");
5097             return E_OUTOFMEMORY;
5098         }
5099     }
5100
5101     for (j = 0; j < 256; ++j) {
5102         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5103         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5104         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5105         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5106     }
5107     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5108     TRACE("(%p) : returning\n", This);
5109     return WINED3D_OK;
5110 }
5111
5112 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5113     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5114     int j;
5115     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5116     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5117         /* What happens in such situation isn't documented; Native seems to silently abort
5118            on such conditions. Return Invalid Call. */
5119         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5120         return WINED3DERR_INVALIDCALL;
5121     }
5122     for (j = 0; j < 256; ++j) {
5123         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5124         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5125         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5126         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5127     }
5128     TRACE("(%p) : returning\n", This);
5129     return WINED3D_OK;
5130 }
5131
5132 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5134     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5135     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5136        (tested with reference rasterizer). Return Invalid Call. */
5137     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5138         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5139         return WINED3DERR_INVALIDCALL;
5140     }
5141     /*TODO: stateblocks */
5142     if (This->currentPalette != PaletteNumber) {
5143         This->currentPalette = PaletteNumber;
5144         dirtify_p8_texture_samplers(This);
5145     }
5146     TRACE("(%p) : returning\n", This);
5147     return WINED3D_OK;
5148 }
5149
5150 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5151     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5152     if (PaletteNumber == NULL) {
5153         WARN("(%p) : returning Invalid Call\n", This);
5154         return WINED3DERR_INVALIDCALL;
5155     }
5156     /*TODO: stateblocks */
5157     *PaletteNumber = This->currentPalette;
5158     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5159     return WINED3D_OK;
5160 }
5161
5162 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5164     static BOOL warned;
5165     if (!warned)
5166     {
5167         FIXME("(%p) : stub\n", This);
5168         warned = TRUE;
5169     }
5170
5171     This->softwareVertexProcessing = bSoftware;
5172     return WINED3D_OK;
5173 }
5174
5175
5176 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5177     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5178     static BOOL warned;
5179     if (!warned)
5180     {
5181         FIXME("(%p) : stub\n", This);
5182         warned = TRUE;
5183     }
5184     return This->softwareVertexProcessing;
5185 }
5186
5187 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface,
5188         UINT swapchain_idx, WINED3DRASTER_STATUS *raster_status)
5189 {
5190     IWineD3DSwapChain *swapchain;
5191     HRESULT hr;
5192
5193     TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
5194             iface, swapchain_idx, raster_status);
5195
5196     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5197     if (FAILED(hr))
5198     {
5199         WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx, hr);
5200         return hr;
5201     }
5202
5203     hr = IWineD3DSwapChain_GetRasterStatus(swapchain, raster_status);
5204     IWineD3DSwapChain_Release(swapchain);
5205     if (FAILED(hr))
5206     {
5207         WARN("Failed to get raster status, hr %#x.\n", hr);
5208         return hr;
5209     }
5210
5211     return WINED3D_OK;
5212 }
5213
5214 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments)
5215 {
5216     static BOOL warned;
5217     if(nSegments != 0.0f) {
5218         if (!warned)
5219         {
5220             FIXME("iface %p, nSegments %.8e stub!\n", iface, nSegments);
5221             warned = TRUE;
5222         }
5223     }
5224     return WINED3D_OK;
5225 }
5226
5227 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface)
5228 {
5229     static BOOL warned;
5230     if (!warned)
5231     {
5232         FIXME("iface %p stub!\n", iface);
5233         warned = TRUE;
5234     }
5235     return 0.0f;
5236 }
5237
5238 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
5239         IWineD3DSurface *src_surface, const RECT *src_rect,
5240         IWineD3DSurface *dst_surface, const POINT *dst_point)
5241 {
5242     IWineD3DSurfaceImpl *src_impl = (IWineD3DSurfaceImpl *)src_surface;
5243     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)dst_surface;
5244     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5245     const struct wined3d_format_desc *src_format;
5246     const struct wined3d_format_desc *dst_format;
5247     const struct wined3d_gl_info *gl_info;
5248     struct wined3d_context *context;
5249     const unsigned char *data;
5250     UINT update_w, update_h;
5251     CONVERT_TYPES convert;
5252     UINT src_w, src_h;
5253     UINT dst_x, dst_y;
5254     DWORD sampler;
5255     struct wined3d_format_desc desc;
5256
5257     TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
5258             iface, src_surface, wine_dbgstr_rect(src_rect),
5259             dst_surface, wine_dbgstr_point(dst_point));
5260
5261     if (src_impl->resource.pool != WINED3DPOOL_SYSTEMMEM || dst_impl->resource.pool != WINED3DPOOL_DEFAULT)
5262     {
5263         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
5264                 src_surface, dst_surface);
5265         return WINED3DERR_INVALIDCALL;
5266     }
5267
5268     src_format = src_impl->resource.format_desc;
5269     dst_format = dst_impl->resource.format_desc;
5270
5271     if (src_format->id != dst_format->id)
5272     {
5273         WARN("Source and destination surfaces should have the same format.\n");
5274         return WINED3DERR_INVALIDCALL;
5275     }
5276
5277     dst_x = dst_point ? dst_point->x : 0;
5278     dst_y = dst_point ? dst_point->y : 0;
5279
5280     /* This call loads the OpenGL surface directly, instead of copying the
5281      * surface to the destination's sysmem copy. If surface conversion is
5282      * needed, use BltFast instead to copy in sysmem and use regular surface
5283      * loading. */
5284     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &desc, &convert);
5285     if (convert != NO_CONVERSION || desc.convert)
5286         return IWineD3DSurface_BltFast(dst_surface, dst_x, dst_y, src_surface, src_rect, 0);
5287
5288     context = context_acquire(This, NULL);
5289     gl_info = context->gl_info;
5290
5291     ENTER_GL();
5292     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5293     checkGLcall("glActiveTextureARB");
5294     LEAVE_GL();
5295
5296     /* Make sure the surface is loaded and up to date */
5297     surface_internal_preload(dst_impl, SRGB_RGB);
5298     IWineD3DSurface_BindTexture(dst_surface, FALSE);
5299
5300     src_w = src_impl->currentDesc.Width;
5301     src_h = src_impl->currentDesc.Height;
5302     update_w = src_rect ? src_rect->right - src_rect->left : src_w;
5303     update_h = src_rect ? src_rect->bottom - src_rect->top : src_h;
5304
5305     data = IWineD3DSurface_GetData(src_surface);
5306     if (!data) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n");
5307
5308     ENTER_GL();
5309
5310     if (dst_format->Flags & WINED3DFMT_FLAG_COMPRESSED)
5311     {
5312         UINT row_length = wined3d_format_calculate_size(src_format, 1, update_w, 1);
5313         UINT row_count = (update_h + src_format->block_height - 1) / src_format->block_height;
5314         UINT src_pitch = wined3d_format_calculate_size(src_format, 1, src_w, 1);
5315
5316         if (src_rect)
5317         {
5318             data += (src_rect->top / src_format->block_height) * src_pitch;
5319             data += (src_rect->left / src_format->block_width) * src_format->block_byte_count;
5320         }
5321
5322         TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
5323                 "format %#x, image_size %#x, data %p.\n", dst_impl->texture_target, dst_impl->texture_level,
5324                 dst_x, dst_y, update_w, update_h, dst_format->glFormat, row_count * row_length, data);
5325
5326         if (row_length == src_pitch)
5327         {
5328             GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5329                     dst_x, dst_y, update_w, update_h, dst_format->glInternal, row_count * row_length, data));
5330         }
5331         else
5332         {
5333             UINT row, y;
5334
5335             /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
5336              * can't use the unpack row length like below. */
5337             for (row = 0, y = dst_y; row < row_count; ++row)
5338             {
5339                 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5340                         dst_x, y, update_w, src_format->block_height, dst_format->glInternal, row_length, data));
5341                 y += src_format->block_height;
5342                 data += src_pitch;
5343             }
5344         }
5345         checkGLcall("glCompressedTexSubImage2DARB");
5346     }
5347     else
5348     {
5349         if (src_rect)
5350         {
5351             data += src_rect->top * src_w * src_format->byte_count;
5352             data += src_rect->left * src_format->byte_count;
5353         }
5354
5355         TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n",
5356                 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
5359         glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w);
5360         glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5361                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5362         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
5363         checkGLcall("glTexSubImage2D");
5364     }
5365
5366     LEAVE_GL();
5367     context_release(context);
5368
5369     surface_modify_location(dst_impl, SFLAG_INTEXTURE, TRUE);
5370     sampler = This->rev_tex_unit_map[0];
5371     if (sampler != WINED3D_UNMAPPED_STAGE)
5372     {
5373         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5374     }
5375
5376     return WINED3D_OK;
5377 }
5378
5379 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5380     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5381     struct WineD3DRectPatch *patch;
5382     GLenum old_primitive_type;
5383     unsigned int i;
5384     struct list *e;
5385     BOOL found;
5386     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5387
5388     if(!(Handle || pRectPatchInfo)) {
5389         /* TODO: Write a test for the return value, thus the FIXME */
5390         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5391         return WINED3DERR_INVALIDCALL;
5392     }
5393
5394     if(Handle) {
5395         i = PATCHMAP_HASHFUNC(Handle);
5396         found = FALSE;
5397         LIST_FOR_EACH(e, &This->patches[i]) {
5398             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5399             if(patch->Handle == Handle) {
5400                 found = TRUE;
5401                 break;
5402             }
5403         }
5404
5405         if(!found) {
5406             TRACE("Patch does not exist. Creating a new one\n");
5407             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5408             patch->Handle = Handle;
5409             list_add_head(&This->patches[i], &patch->entry);
5410         } else {
5411             TRACE("Found existing patch %p\n", patch);
5412         }
5413     } else {
5414         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5415          * attributes we have to tesselate, read back, and draw. This needs a patch
5416          * management structure instance. Create one.
5417          *
5418          * A possible improvement is to check if a vertex shader is used, and if not directly
5419          * draw the patch.
5420          */
5421         FIXME("Drawing an uncached patch. This is slow\n");
5422         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5423     }
5424
5425     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5426        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5427        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5428         HRESULT hr;
5429         TRACE("Tesselation density or patch info changed, retesselating\n");
5430
5431         if(pRectPatchInfo) {
5432             patch->RectPatchInfo = *pRectPatchInfo;
5433         }
5434         patch->numSegs[0] = pNumSegs[0];
5435         patch->numSegs[1] = pNumSegs[1];
5436         patch->numSegs[2] = pNumSegs[2];
5437         patch->numSegs[3] = pNumSegs[3];
5438
5439         hr = tesselate_rectpatch(This, patch);
5440         if(FAILED(hr)) {
5441             WARN("Patch tesselation failed\n");
5442
5443             /* Do not release the handle to store the params of the patch */
5444             if(!Handle) {
5445                 HeapFree(GetProcessHeap(), 0, patch);
5446             }
5447             return hr;
5448         }
5449     }
5450
5451     This->currentPatch = patch;
5452     old_primitive_type = This->stateBlock->gl_primitive_type;
5453     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5454     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5455     This->stateBlock->gl_primitive_type = old_primitive_type;
5456     This->currentPatch = NULL;
5457
5458     /* Destroy uncached patches */
5459     if(!Handle) {
5460         HeapFree(GetProcessHeap(), 0, patch->mem);
5461         HeapFree(GetProcessHeap(), 0, patch);
5462     }
5463     return WINED3D_OK;
5464 }
5465
5466 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface,
5467         UINT handle, const float *segment_count, const WINED3DTRIPATCH_INFO *patch_info)
5468 {
5469     FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5470             iface, handle, segment_count, patch_info);
5471
5472     return WINED3D_OK;
5473 }
5474
5475 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5476     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5477     int i;
5478     struct WineD3DRectPatch *patch;
5479     struct list *e;
5480     TRACE("(%p) Handle(%d)\n", This, Handle);
5481
5482     i = PATCHMAP_HASHFUNC(Handle);
5483     LIST_FOR_EACH(e, &This->patches[i]) {
5484         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5485         if(patch->Handle == Handle) {
5486             TRACE("Deleting patch %p\n", patch);
5487             list_remove(&patch->entry);
5488             HeapFree(GetProcessHeap(), 0, patch->mem);
5489             HeapFree(GetProcessHeap(), 0, patch);
5490             return WINED3D_OK;
5491         }
5492     }
5493
5494     /* TODO: Write a test for the return value */
5495     FIXME("Attempt to destroy nonexistent patch\n");
5496     return WINED3DERR_INVALIDCALL;
5497 }
5498
5499 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface,
5500         IWineD3DSurface *surface, const WINED3DRECT *pRect, const WINED3DCOLORVALUE *color)
5501 {
5502     IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)surface;
5503     WINEDDBLTFX BltFx;
5504
5505     TRACE("iface %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
5506             iface, surface, wine_dbgstr_rect((const RECT *)pRect),
5507             color->r, color->g, color->b, color->a);
5508
5509     if (s->resource.pool != WINED3DPOOL_DEFAULT && s->resource.pool != WINED3DPOOL_SYSTEMMEM)
5510     {
5511         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5512         return WINED3DERR_INVALIDCALL;
5513     }
5514
5515     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
5516     {
5517         const RECT draw_rect = {0, 0, s->currentDesc.Width, s->currentDesc.Height};
5518
5519         return device_clear_render_targets((IWineD3DDeviceImpl *)iface, 1, &s,
5520                 !!pRect, (const RECT *)pRect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0);
5521     }
5522     else
5523     {
5524         /* Just forward this to the DirectDraw blitting engine */
5525         memset(&BltFx, 0, sizeof(BltFx));
5526         BltFx.dwSize = sizeof(BltFx);
5527         BltFx.u5.dwFillColor = wined3d_format_convert_from_float(s->resource.format_desc, color);
5528         return IWineD3DSurface_Blt(surface, (const RECT *)pRect, NULL, NULL,
5529                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
5530     }
5531 }
5532
5533 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
5534         IWineD3DRendertargetView *rendertarget_view, const WINED3DCOLORVALUE *color)
5535 {
5536     IWineD3DResource *resource;
5537     IWineD3DSurfaceImpl *surface;
5538     HRESULT hr;
5539
5540     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
5541     if (FAILED(hr))
5542     {
5543         ERR("Failed to get resource, hr %#x\n", hr);
5544         return;
5545     }
5546
5547     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
5548     {
5549         FIXME("Only supported on surface resources\n");
5550         IWineD3DResource_Release(resource);
5551         return;
5552     }
5553
5554     surface = (IWineD3DSurfaceImpl *)resource;
5555
5556     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
5557     {
5558         const RECT draw_rect = {0, 0, surface->currentDesc.Width, surface->currentDesc.Height};
5559
5560         device_clear_render_targets((IWineD3DDeviceImpl *)iface, 1, &surface,
5561                 0, NULL, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0);
5562     }
5563     else
5564     {
5565         WINEDDBLTFX BltFx;
5566
5567         /* Just forward this to the DirectDraw blitting engine */
5568         memset(&BltFx, 0, sizeof(BltFx));
5569         BltFx.dwSize = sizeof(BltFx);
5570         BltFx.u5.dwFillColor = wined3d_format_convert_from_float(surface->resource.format_desc, color);
5571         hr = IWineD3DSurface_Blt((IWineD3DSurface *)surface, NULL, NULL, NULL,
5572                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
5573         if (FAILED(hr))
5574         {
5575             ERR("Blt failed, hr %#x\n", hr);
5576         }
5577     }
5578
5579     IWineD3DResource_Release(resource);
5580 }
5581
5582 /* rendertarget and depth stencil functions */
5583 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice *iface,
5584         DWORD render_target_idx, IWineD3DSurface **render_target)
5585 {
5586     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5587
5588     TRACE("iface %p, render_target_idx %u, render_target %p.\n",
5589             iface, render_target_idx, render_target);
5590
5591     if (render_target_idx >= device->adapter->gl_info.limits.buffers)
5592     {
5593         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
5594         return WINED3DERR_INVALIDCALL;
5595     }
5596
5597     *render_target = (IWineD3DSurface *)device->render_targets[render_target_idx];
5598     if (*render_target) IWineD3DSurface_AddRef(*render_target);
5599
5600     TRACE("Returning render target %p.\n", *render_target);
5601
5602     return WINED3D_OK;
5603 }
5604
5605 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface,
5606         IWineD3DSurface *front, IWineD3DSurface *back)
5607 {
5608     IWineD3DSurfaceImpl *front_impl = (IWineD3DSurfaceImpl *)front;
5609     IWineD3DSurfaceImpl *back_impl = (IWineD3DSurfaceImpl *)back;
5610     IWineD3DSwapChainImpl *swapchain;
5611     HRESULT hr;
5612
5613     TRACE("iface %p, front %p, back %p.\n", iface, front, back);
5614
5615     if (FAILED(hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&swapchain)))
5616     {
5617         ERR("Failed to get the swapchain, hr %#x.\n", hr);
5618         return hr;
5619     }
5620
5621     if (front_impl && !(front_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5622     {
5623         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5624         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5625         return WINED3DERR_INVALIDCALL;
5626     }
5627
5628     if (back_impl)
5629     {
5630         if (!(back_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5631         {
5632             ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5633             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5634             return WINED3DERR_INVALIDCALL;
5635         }
5636
5637         if (!swapchain->back_buffers)
5638         {
5639             swapchain->back_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*swapchain->back_buffers));
5640             if (!swapchain->back_buffers)
5641             {
5642                 ERR("Failed to allocate back buffer array memory.\n");
5643                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5644                 return E_OUTOFMEMORY;
5645             }
5646         }
5647     }
5648
5649     if (swapchain->front_buffer != front_impl)
5650     {
5651         TRACE("Changing the front buffer from %p to %p.\n", swapchain->front_buffer, front_impl);
5652
5653         if (swapchain->front_buffer)
5654             surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_NONE, NULL);
5655         swapchain->front_buffer = front_impl;
5656
5657         if (front_impl)
5658             surface_set_container(front_impl, WINED3D_CONTAINER_SWAPCHAIN, (IWineD3DBase *)swapchain);
5659     }
5660
5661     if (swapchain->back_buffers[0] != back_impl)
5662     {
5663         TRACE("Changing the back buffer from %p to %p.\n", swapchain->back_buffers[0], back_impl);
5664
5665         if (swapchain->back_buffers[0])
5666             surface_set_container(swapchain->back_buffers[0], WINED3D_CONTAINER_NONE, NULL);
5667         swapchain->back_buffers[0] = back_impl;
5668
5669         if (back_impl)
5670         {
5671             swapchain->presentParms.BackBufferWidth = back_impl->currentDesc.Width;
5672             swapchain->presentParms.BackBufferHeight = back_impl->currentDesc.Height;
5673             swapchain->presentParms.BackBufferFormat = back_impl->resource.format_desc->id;
5674             swapchain->presentParms.BackBufferCount = 1;
5675
5676             surface_set_container(back_impl, WINED3D_CONTAINER_SWAPCHAIN, (IWineD3DBase *)swapchain);
5677         }
5678         else
5679         {
5680             swapchain->presentParms.BackBufferCount = 0;
5681             HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
5682             swapchain->back_buffers = NULL;
5683         }
5684     }
5685
5686     IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5687     return WINED3D_OK;
5688 }
5689
5690 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface **depth_stencil)
5691 {
5692     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5693
5694     TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
5695
5696     *depth_stencil = (IWineD3DSurface *)device->depth_stencil;
5697     TRACE("Returning depth/stencil surface %p.\n", *depth_stencil);
5698     if (!*depth_stencil) return WINED3DERR_NOTFOUND;
5699     IWineD3DSurface_AddRef(*depth_stencil);
5700
5701     return WINED3D_OK;
5702 }
5703
5704 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
5705         DWORD render_target_idx, IWineD3DSurface *render_target, BOOL set_viewport)
5706 {
5707     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5708     IWineD3DSurfaceImpl *prev;
5709
5710     TRACE("iface %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
5711             iface, render_target_idx, render_target, set_viewport);
5712
5713     if (render_target_idx >= device->adapter->gl_info.limits.buffers)
5714     {
5715         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
5716         return WINED3DERR_INVALIDCALL;
5717     }
5718
5719     prev = device->render_targets[render_target_idx];
5720     if (render_target == (IWineD3DSurface *)prev)
5721     {
5722         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5723         return WINED3D_OK;
5724     }
5725
5726     /* Render target 0 can't be set to NULL. */
5727     if (!render_target && !render_target_idx)
5728     {
5729         WARN("Trying to set render target 0 to NULL.\n");
5730         return WINED3DERR_INVALIDCALL;
5731     }
5732
5733     if (render_target && !(((IWineD3DSurfaceImpl *)render_target)->resource.usage & WINED3DUSAGE_RENDERTARGET))
5734     {
5735         FIXME("Surface %p doesn't have render target usage.\n", render_target);
5736         return WINED3DERR_INVALIDCALL;
5737     }
5738
5739     if (render_target) IWineD3DSurface_AddRef(render_target);
5740     device->render_targets[render_target_idx] = (IWineD3DSurfaceImpl *)render_target;
5741     /* Release after the assignment, to prevent device_resource_released()
5742      * from seeing the surface as still in use. */
5743     if (prev) IWineD3DSurface_Release((IWineD3DSurface *)prev);
5744
5745     /* Render target 0 is special. */
5746     if (!render_target_idx && set_viewport)
5747     {
5748         /* Set the viewport and scissor rectangles, if requested. Tests show
5749          * that stateblock recording is ignored, the change goes directly
5750          * into the primary stateblock. */
5751         device->stateBlock->viewport.Height = device->render_targets[0]->currentDesc.Height;
5752         device->stateBlock->viewport.Width  = device->render_targets[0]->currentDesc.Width;
5753         device->stateBlock->viewport.X      = 0;
5754         device->stateBlock->viewport.Y      = 0;
5755         device->stateBlock->viewport.MaxZ   = 1.0f;
5756         device->stateBlock->viewport.MinZ   = 0.0f;
5757         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_VIEWPORT);
5758
5759         device->stateBlock->scissorRect.top = 0;
5760         device->stateBlock->scissorRect.left = 0;
5761         device->stateBlock->scissorRect.right = device->stateBlock->viewport.Width;
5762         device->stateBlock->scissorRect.bottom = device->stateBlock->viewport.Height;
5763         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SCISSORRECT);
5764     }
5765
5766     return WINED3D_OK;
5767 }
5768
5769 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil)
5770 {
5771     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5772     IWineD3DSurfaceImpl *tmp;
5773
5774     TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This, depth_stencil, This->depth_stencil);
5775
5776     if (This->depth_stencil == (IWineD3DSurfaceImpl *)depth_stencil)
5777     {
5778         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5779         return WINED3D_OK;
5780     }
5781
5782     if (This->depth_stencil)
5783     {
5784         if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5785                 || This->depth_stencil->Flags & SFLAG_DISCARD)
5786         {
5787             surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED,
5788                     This->depth_stencil->currentDesc.Width,
5789                     This->depth_stencil->currentDesc.Height);
5790             if (This->depth_stencil == This->onscreen_depth_stencil)
5791             {
5792                 IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
5793                 This->onscreen_depth_stencil = NULL;
5794             }
5795         }
5796     }
5797
5798     tmp = This->depth_stencil;
5799     This->depth_stencil = (IWineD3DSurfaceImpl *)depth_stencil;
5800     if (This->depth_stencil) IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil);
5801     if (tmp) IWineD3DSurface_Release((IWineD3DSurface *)tmp);
5802
5803     if ((!tmp && depth_stencil) || (!depth_stencil && tmp))
5804     {
5805         /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5806         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5807         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5808         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5809     }
5810
5811     return WINED3D_OK;
5812 }
5813
5814 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice *iface,
5815         UINT XHotSpot, UINT YHotSpot, IWineD3DSurface *cursor_image)
5816 {
5817     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5818     IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)cursor_image;
5819     WINED3DLOCKED_RECT lockedRect;
5820
5821     TRACE("iface %p, hotspot_x %u, hotspot_y %u, cursor_image %p.\n",
5822             iface, XHotSpot, YHotSpot, cursor_image);
5823
5824     /* some basic validation checks */
5825     if (This->cursorTexture)
5826     {
5827         struct wined3d_context *context = context_acquire(This, NULL);
5828         ENTER_GL();
5829         glDeleteTextures(1, &This->cursorTexture);
5830         LEAVE_GL();
5831         context_release(context);
5832         This->cursorTexture = 0;
5833     }
5834
5835     if ((s->currentDesc.Width == 32) && (s->currentDesc.Height == 32))
5836         This->haveHardwareCursor = TRUE;
5837     else
5838         This->haveHardwareCursor = FALSE;
5839
5840     if (cursor_image)
5841     {
5842         WINED3DLOCKED_RECT rect;
5843
5844         /* MSDN: Cursor must be A8R8G8B8 */
5845         if (s->resource.format_desc->id != WINED3DFMT_B8G8R8A8_UNORM)
5846         {
5847             WARN("surface %p has an invalid format.\n", cursor_image);
5848             return WINED3DERR_INVALIDCALL;
5849         }
5850
5851         /* MSDN: Cursor must be smaller than the display mode */
5852         if (s->currentDesc.Width > This->ddraw_width
5853                 || s->currentDesc.Height > This->ddraw_height)
5854         {
5855             WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
5856                     s, s->currentDesc.Width, s->currentDesc.Height, This->ddraw_width, This->ddraw_height);
5857             return WINED3DERR_INVALIDCALL;
5858         }
5859
5860         if (!This->haveHardwareCursor) {
5861             /* TODO: MSDN: Cursor sizes must be a power of 2 */
5862
5863             /* Do not store the surface's pointer because the application may
5864              * release it after setting the cursor image. Windows doesn't
5865              * addref the set surface, so we can't do this either without
5866              * creating circular refcount dependencies. Copy out the gl texture
5867              * instead.
5868              */
5869             This->cursorWidth = s->currentDesc.Width;
5870             This->cursorHeight = s->currentDesc.Height;
5871             if (SUCCEEDED(IWineD3DSurface_LockRect(cursor_image, &rect, NULL, WINED3DLOCK_READONLY)))
5872             {
5873                 const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
5874                 const struct wined3d_format_desc *format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info);
5875                 struct wined3d_context *context;
5876                 char *mem, *bits = rect.pBits;
5877                 GLint intfmt = format_desc->glInternal;
5878                 GLint format = format_desc->glFormat;
5879                 GLint type = format_desc->glType;
5880                 INT height = This->cursorHeight;
5881                 INT width = This->cursorWidth;
5882                 INT bpp = format_desc->byte_count;
5883                 DWORD sampler;
5884                 INT i;
5885
5886                 /* Reformat the texture memory (pitch and width can be
5887                  * different) */
5888                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
5889                 for(i = 0; i < height; i++)
5890                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
5891                 IWineD3DSurface_UnlockRect(cursor_image);
5892
5893                 context = context_acquire(This, NULL);
5894
5895                 ENTER_GL();
5896
5897                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
5898                 {
5899                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
5900                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5901                 }
5902
5903                 /* Make sure that a proper texture unit is selected */
5904                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5905                 checkGLcall("glActiveTextureARB");
5906                 sampler = This->rev_tex_unit_map[0];
5907                 if (sampler != WINED3D_UNMAPPED_STAGE)
5908                 {
5909                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5910                 }
5911                 /* Create a new cursor texture */
5912                 glGenTextures(1, &This->cursorTexture);
5913                 checkGLcall("glGenTextures");
5914                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
5915                 checkGLcall("glBindTexture");
5916                 /* Copy the bitmap memory into the cursor texture */
5917                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
5918                 HeapFree(GetProcessHeap(), 0, mem);
5919                 checkGLcall("glTexImage2D");
5920
5921                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
5922                 {
5923                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
5924                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
5925                 }
5926
5927                 LEAVE_GL();
5928
5929                 context_release(context);
5930             }
5931             else
5932             {
5933                 FIXME("A cursor texture was not returned.\n");
5934                 This->cursorTexture = 0;
5935             }
5936         }
5937         else
5938         {
5939             /* Draw a hardware cursor */
5940             ICONINFO cursorInfo;
5941             HCURSOR cursor;
5942             /* Create and clear maskBits because it is not needed for
5943              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
5944              * chunks. */
5945             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5946                     (s->currentDesc.Width * s->currentDesc.Height / 8));
5947             IWineD3DSurface_LockRect(cursor_image, &lockedRect, NULL,
5948                     WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY);
5949             TRACE("width: %u height: %u.\n", s->currentDesc.Width, s->currentDesc.Height);
5950
5951             cursorInfo.fIcon = FALSE;
5952             cursorInfo.xHotspot = XHotSpot;
5953             cursorInfo.yHotspot = YHotSpot;
5954             cursorInfo.hbmMask = CreateBitmap(s->currentDesc.Width, s->currentDesc.Height, 1, 1, maskBits);
5955             cursorInfo.hbmColor = CreateBitmap(s->currentDesc.Width, s->currentDesc.Height, 1, 32, lockedRect.pBits);
5956             IWineD3DSurface_UnlockRect(cursor_image);
5957             /* Create our cursor and clean up. */
5958             cursor = CreateIconIndirect(&cursorInfo);
5959             SetCursor(cursor);
5960             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
5961             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
5962             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
5963             This->hardwareCursor = cursor;
5964             HeapFree(GetProcessHeap(), 0, maskBits);
5965         }
5966     }
5967
5968     This->xHotSpot = XHotSpot;
5969     This->yHotSpot = YHotSpot;
5970     return WINED3D_OK;
5971 }
5972
5973 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5974     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5975     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5976
5977     This->xScreenSpace = XScreenSpace;
5978     This->yScreenSpace = YScreenSpace;
5979
5980     return;
5981
5982 }
5983
5984 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5985     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5986     BOOL oldVisible = This->bCursorVisible;
5987     POINT pt;
5988
5989     TRACE("(%p) : visible(%d)\n", This, bShow);
5990
5991     /*
5992      * When ShowCursor is first called it should make the cursor appear at the OS's last
5993      * known cursor position.  Because of this, some applications just repetitively call
5994      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5995      */
5996     GetCursorPos(&pt);
5997     This->xScreenSpace = pt.x;
5998     This->yScreenSpace = pt.y;
5999
6000     if (This->haveHardwareCursor) {
6001         This->bCursorVisible = bShow;
6002         if (bShow)
6003             SetCursor(This->hardwareCursor);
6004         else
6005             SetCursor(NULL);
6006     }
6007     else
6008     {
6009         if (This->cursorTexture)
6010             This->bCursorVisible = bShow;
6011     }
6012
6013     return oldVisible;
6014 }
6015
6016 static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) {
6017     TRACE("checking resource %p for eviction\n", resource);
6018     if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) {
6019         TRACE("Evicting %p\n", resource);
6020         IWineD3DResource_UnLoad(resource);
6021     }
6022     IWineD3DResource_Release(resource);
6023     return S_OK;
6024 }
6025
6026 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice *iface)
6027 {
6028     TRACE("iface %p.\n", iface);
6029
6030     IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL);
6031     /* Invalidate stream sources, the buffer(s) may have been evicted. */
6032     IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)iface, STATE_STREAMSRC);
6033
6034     return WINED3D_OK;
6035 }
6036
6037 static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
6038 {
6039     IWineD3DDeviceImpl *device = surface->resource.device;
6040     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6041
6042     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6043     if(surface->Flags & SFLAG_DIBSECTION) {
6044         /* Release the DC */
6045         SelectObject(surface->hDC, surface->dib.holdbitmap);
6046         DeleteDC(surface->hDC);
6047         /* Release the DIB section */
6048         DeleteObject(surface->dib.DIBsection);
6049         surface->dib.bitmap_data = NULL;
6050         surface->resource.allocatedMemory = NULL;
6051         surface->Flags &= ~SFLAG_DIBSECTION;
6052     }
6053     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6054     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6055     if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
6056             || gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
6057     {
6058         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6059         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6060     } else {
6061         surface->pow2Width = surface->pow2Height = 1;
6062         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6063         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6064     }
6065
6066     if (surface->texture_name)
6067     {
6068         struct wined3d_context *context = context_acquire(device, NULL);
6069         ENTER_GL();
6070         glDeleteTextures(1, &surface->texture_name);
6071         LEAVE_GL();
6072         context_release(context);
6073         surface->texture_name = 0;
6074         surface->Flags &= ~SFLAG_CLIENT;
6075     }
6076     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6077        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6078         surface->Flags |= SFLAG_NONPOW2;
6079     } else  {
6080         surface->Flags &= ~SFLAG_NONPOW2;
6081     }
6082     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
6083     surface->resource.allocatedMemory = NULL;
6084     surface->resource.heapMemory = NULL;
6085     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6086
6087     /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6088      * to a FBO */
6089     if (!surface_init_sysmem(surface))
6090     {
6091         return E_OUTOFMEMORY;
6092     }
6093     return WINED3D_OK;
6094 }
6095
6096 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6097     TRACE("Unloading resource %p\n", resource);
6098     IWineD3DResource_UnLoad(resource);
6099     IWineD3DResource_Release(resource);
6100     return S_OK;
6101 }
6102
6103 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
6104 {
6105     UINT i, count;
6106     WINED3DDISPLAYMODE m;
6107     HRESULT hr;
6108
6109     /* All Windowed modes are supported, as is leaving the current mode */
6110     if(pp->Windowed) return TRUE;
6111     if(!pp->BackBufferWidth) return TRUE;
6112     if(!pp->BackBufferHeight) return TRUE;
6113
6114     count = IWineD3D_GetAdapterModeCount(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN);
6115     for(i = 0; i < count; i++) {
6116         memset(&m, 0, sizeof(m));
6117         hr = IWineD3D_EnumAdapterModes(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN, i, &m);
6118         if(FAILED(hr)) {
6119             ERR("EnumAdapterModes failed\n");
6120         }
6121         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
6122             /* Mode found, it is supported */
6123             return TRUE;
6124         }
6125     }
6126     /* Mode not found -> not supported */
6127     return FALSE;
6128 }
6129
6130 static void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6131 {
6132     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6133     const struct wined3d_gl_info *gl_info;
6134     struct wined3d_context *context;
6135     IWineD3DBaseShaderImpl *shader;
6136
6137     context = context_acquire(This, NULL);
6138     gl_info = context->gl_info;
6139
6140     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6141     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6142         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6143     }
6144
6145     ENTER_GL();
6146     if(This->depth_blt_texture) {
6147         glDeleteTextures(1, &This->depth_blt_texture);
6148         This->depth_blt_texture = 0;
6149     }
6150     if (This->depth_blt_rb) {
6151         gl_info->fbo_ops.glDeleteRenderbuffers(1, &This->depth_blt_rb);
6152         This->depth_blt_rb = 0;
6153         This->depth_blt_rb_w = 0;
6154         This->depth_blt_rb_h = 0;
6155     }
6156     LEAVE_GL();
6157
6158     This->blitter->free_private(iface);
6159     This->frag_pipe->free_private(iface);
6160     This->shader_backend->shader_free_private(iface);
6161     destroy_dummy_textures(This, gl_info);
6162
6163     context_release(context);
6164
6165     while (This->numContexts)
6166     {
6167         context_destroy(This, This->contexts[0]);
6168     }
6169     HeapFree(GetProcessHeap(), 0, swapchain->context);
6170     swapchain->context = NULL;
6171     swapchain->num_contexts = 0;
6172 }
6173
6174 static HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6175 {
6176     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6177     struct wined3d_context *context;
6178     HRESULT hr;
6179     IWineD3DSurfaceImpl *target;
6180
6181     /* Recreate the primary swapchain's context */
6182     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
6183     if (!swapchain->context)
6184     {
6185         ERR("Failed to allocate memory for swapchain context array.\n");
6186         return E_OUTOFMEMORY;
6187     }
6188
6189     target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
6190     if (!(context = context_create(swapchain, target, swapchain->ds_format)))
6191     {
6192         WARN("Failed to create context.\n");
6193         HeapFree(GetProcessHeap(), 0, swapchain->context);
6194         return E_FAIL;
6195     }
6196
6197     swapchain->context[0] = context;
6198     swapchain->num_contexts = 1;
6199     create_dummy_textures(This);
6200     context_release(context);
6201
6202     hr = This->shader_backend->shader_alloc_private(iface);
6203     if (FAILED(hr))
6204     {
6205         ERR("Failed to allocate shader private data, hr %#x.\n", hr);
6206         goto err;
6207     }
6208
6209     hr = This->frag_pipe->alloc_private(iface);
6210     if (FAILED(hr))
6211     {
6212         ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr);
6213         This->shader_backend->shader_free_private(iface);
6214         goto err;
6215     }
6216
6217     hr = This->blitter->alloc_private(iface);
6218     if (FAILED(hr))
6219     {
6220         ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
6221         This->frag_pipe->free_private(iface);
6222         This->shader_backend->shader_free_private(iface);
6223         goto err;
6224     }
6225
6226     return WINED3D_OK;
6227
6228 err:
6229     context_acquire(This, NULL);
6230     destroy_dummy_textures(This, context->gl_info);
6231     context_release(context);
6232     context_destroy(This, context);
6233     HeapFree(GetProcessHeap(), 0, swapchain->context);
6234     swapchain->num_contexts = 0;
6235     return hr;
6236 }
6237
6238 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6239     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6240     IWineD3DSwapChainImpl *swapchain;
6241     HRESULT hr;
6242     BOOL DisplayModeChanged = FALSE;
6243     WINED3DDISPLAYMODE mode;
6244     TRACE("(%p)\n", This);
6245
6246     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6247     if(FAILED(hr)) {
6248         ERR("Failed to get the first implicit swapchain\n");
6249         return hr;
6250     }
6251
6252     if(!is_display_mode_supported(This, pPresentationParameters)) {
6253         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6254         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
6255              pPresentationParameters->BackBufferHeight);
6256         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6257         return WINED3DERR_INVALIDCALL;
6258     }
6259
6260     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6261      * on an existing gl context, so there's no real need for recreation.
6262      *
6263      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6264      *
6265      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6266      */
6267     TRACE("New params:\n");
6268     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6269     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6270     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6271     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6272     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6273     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6274     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6275     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6276     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6277     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6278     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6279     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6280     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6281
6282     /* No special treatment of these parameters. Just store them */
6283     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6284     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6285     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6286     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6287
6288     /* What to do about these? */
6289     if(pPresentationParameters->BackBufferCount != 0 &&
6290         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6291         ERR("Cannot change the back buffer count yet\n");
6292     }
6293     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6294         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6295         ERR("Cannot change the back buffer format yet\n");
6296     }
6297     if(pPresentationParameters->hDeviceWindow != NULL &&
6298         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6299         ERR("Cannot change the device window yet\n");
6300     }
6301     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil)
6302     {
6303         HRESULT hrc;
6304
6305         TRACE("Creating the depth stencil buffer\n");
6306
6307         hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
6308                 This->parent,
6309                 pPresentationParameters->BackBufferWidth,
6310                 pPresentationParameters->BackBufferHeight,
6311                 pPresentationParameters->AutoDepthStencilFormat,
6312                 pPresentationParameters->MultiSampleType,
6313                 pPresentationParameters->MultiSampleQuality,
6314                 FALSE,
6315                 (IWineD3DSurface **)&This->auto_depth_stencil);
6316
6317         if (FAILED(hrc)) {
6318             ERR("Failed to create the depth stencil buffer\n");
6319             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6320             return WINED3DERR_INVALIDCALL;
6321         }
6322     }
6323
6324     if (This->onscreen_depth_stencil)
6325     {
6326         IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
6327         This->onscreen_depth_stencil = NULL;
6328     }
6329
6330     /* Reset the depth stencil */
6331     if (pPresentationParameters->EnableAutoDepthStencil)
6332         IWineD3DDevice_SetDepthStencilSurface(iface, (IWineD3DSurface *)This->auto_depth_stencil);
6333     else
6334         IWineD3DDevice_SetDepthStencilSurface(iface, NULL);
6335
6336     TRACE("Resetting stateblock\n");
6337     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
6338     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
6339
6340     delete_opengl_contexts(iface, swapchain);
6341
6342     if(pPresentationParameters->Windowed) {
6343         mode.Width = swapchain->orig_width;
6344         mode.Height = swapchain->orig_height;
6345         mode.RefreshRate = 0;
6346         mode.Format = swapchain->presentParms.BackBufferFormat;
6347     } else {
6348         mode.Width = pPresentationParameters->BackBufferWidth;
6349         mode.Height = pPresentationParameters->BackBufferHeight;
6350         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6351         mode.Format = swapchain->presentParms.BackBufferFormat;
6352     }
6353
6354     /* Should Width == 800 && Height == 0 set 800x600? */
6355     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6356        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6357         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6358     {
6359         UINT i;
6360
6361         if(!pPresentationParameters->Windowed) {
6362             DisplayModeChanged = TRUE;
6363         }
6364         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6365         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6366
6367         hr = updateSurfaceDesc(swapchain->front_buffer, pPresentationParameters);
6368         if(FAILED(hr))
6369         {
6370             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6371             return hr;
6372         }
6373
6374         for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i)
6375         {
6376             hr = updateSurfaceDesc(swapchain->back_buffers[i], pPresentationParameters);
6377             if(FAILED(hr))
6378             {
6379                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6380                 return hr;
6381             }
6382         }
6383         if (This->auto_depth_stencil)
6384         {
6385             hr = updateSurfaceDesc(This->auto_depth_stencil, pPresentationParameters);
6386             if(FAILED(hr))
6387             {
6388                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6389                 return hr;
6390             }
6391         }
6392     }
6393
6394     if (!pPresentationParameters->Windowed != !swapchain->presentParms.Windowed
6395             || DisplayModeChanged)
6396     {
6397         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6398
6399         if (!pPresentationParameters->Windowed)
6400         {
6401             if(swapchain->presentParms.Windowed) {
6402                 /* switch from windowed to fs */
6403                 swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6404                         pPresentationParameters->BackBufferHeight);
6405             } else {
6406                 /* Fullscreen -> fullscreen mode change */
6407                 MoveWindow(swapchain->device_window, 0, 0,
6408                            pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
6409                            TRUE);
6410             }
6411         }
6412         else if (!swapchain->presentParms.Windowed)
6413         {
6414             /* Fullscreen -> windowed switch */
6415             swapchain_restore_fullscreen_window(swapchain);
6416         }
6417         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6418     } else if(!pPresentationParameters->Windowed) {
6419         DWORD style = This->style, exStyle = This->exStyle;
6420         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6421          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6422          * Reset to clear up their mess. Guild Wars also loses the device during that.
6423          */
6424         This->style = 0;
6425         This->exStyle = 0;
6426         swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6427                 pPresentationParameters->BackBufferHeight);
6428         This->style = style;
6429         This->exStyle = exStyle;
6430     }
6431
6432     /* Note: No parent needed for initial internal stateblock */
6433     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock);
6434     if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6435     else TRACE("Created stateblock %p\n", This->stateBlock);
6436     This->updateStateBlock = This->stateBlock;
6437     IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
6438
6439     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
6440     if(FAILED(hr)) {
6441         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6442     }
6443
6444     if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
6445     {
6446         RECT client_rect;
6447         GetClientRect(swapchain->win_handle, &client_rect);
6448
6449         if(!swapchain->presentParms.BackBufferCount)
6450         {
6451             TRACE("Single buffered rendering\n");
6452             swapchain->render_to_fbo = FALSE;
6453         }
6454         else if(swapchain->presentParms.BackBufferWidth  != client_rect.right  ||
6455                 swapchain->presentParms.BackBufferHeight != client_rect.bottom )
6456         {
6457             TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6458                     swapchain->presentParms.BackBufferWidth,
6459                     swapchain->presentParms.BackBufferHeight,
6460                     client_rect.right, client_rect.bottom);
6461             swapchain->render_to_fbo = TRUE;
6462         }
6463         else
6464         {
6465             TRACE("Rendering directly to GL_BACK\n");
6466             swapchain->render_to_fbo = FALSE;
6467         }
6468     }
6469
6470     hr = create_primary_opengl_context(iface, swapchain);
6471     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6472
6473     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6474      * first use
6475      */
6476     return hr;
6477 }
6478
6479 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL enable_dialogs)
6480 {
6481     TRACE("iface %p, enable_dialogs %#x.\n", iface, enable_dialogs);
6482
6483     if (!enable_dialogs) FIXME("Dialogs cannot be disabled yet.\n");
6484
6485     return WINED3D_OK;
6486 }
6487
6488
6489 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6490     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6491     TRACE("(%p) : pParameters %p\n", This, pParameters);
6492
6493     *pParameters = This->createParms;
6494     return WINED3D_OK;
6495 }
6496
6497 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6498     IWineD3DSwapChain *swapchain;
6499
6500     TRACE("Relaying  to swapchain\n");
6501
6502     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6503         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, pRamp);
6504         IWineD3DSwapChain_Release(swapchain);
6505     }
6506 }
6507
6508 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6509     IWineD3DSwapChain *swapchain;
6510
6511     TRACE("Relaying  to swapchain\n");
6512
6513     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6514         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6515         IWineD3DSwapChain_Release(swapchain);
6516     }
6517 }
6518
6519
6520 /** ********************************************************
6521 *   Notification functions
6522 ** ********************************************************/
6523 /** This function must be called in the release of a resource when ref == 0,
6524 * the contents of resource must still be correct,
6525 * any handles to other resource held by the caller must be closed
6526 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6527  *****************************************************/
6528 void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6529 {
6530     TRACE("(%p) : Adding resource %p\n", This, resource);
6531
6532     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6533 }
6534
6535 static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6536 {
6537     TRACE("(%p) : Removing resource %p\n", This, resource);
6538
6539     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6540 }
6541
6542 void device_resource_released(IWineD3DDeviceImpl *device, IWineD3DResource *resource)
6543 {
6544     WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource);
6545     unsigned int i;
6546
6547     TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type));
6548
6549     context_resource_released(device, resource, type);
6550
6551     switch (type)
6552     {
6553         case WINED3DRTYPE_SURFACE:
6554             if (!device->d3d_initialized) break;
6555
6556             for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
6557             {
6558                 if (device->render_targets[i] == (IWineD3DSurfaceImpl *)resource)
6559                 {
6560                     ERR("Surface %p is still in use as render target %u.\n", resource, i);
6561                     device->render_targets[i] = NULL;
6562                 }
6563             }
6564
6565             if (device->depth_stencil == (IWineD3DSurfaceImpl *)resource)
6566             {
6567                 ERR("Surface %p is still in use as depth/stencil buffer.\n", resource);
6568                 device->depth_stencil = NULL;
6569             }
6570             break;
6571
6572         case WINED3DRTYPE_TEXTURE:
6573         case WINED3DRTYPE_CUBETEXTURE:
6574         case WINED3DRTYPE_VOLUMETEXTURE:
6575             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
6576             {
6577                 if (device->stateBlock && device->stateBlock->textures[i] == (IWineD3DBaseTexture *)resource)
6578                 {
6579                     ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6580                             resource, device->stateBlock, i);
6581                     device->stateBlock->textures[i] = NULL;
6582                 }
6583
6584                 if (device->updateStateBlock != device->stateBlock
6585                         && device->updateStateBlock->textures[i] == (IWineD3DBaseTexture *)resource)
6586                 {
6587                     ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6588                             resource, device->updateStateBlock, i);
6589                     device->updateStateBlock->textures[i] = NULL;
6590                 }
6591             }
6592             break;
6593
6594         case WINED3DRTYPE_BUFFER:
6595             for (i = 0; i < MAX_STREAMS; ++i)
6596             {
6597                 if (device->stateBlock && device->stateBlock->streamSource[i] == (IWineD3DBuffer *)resource)
6598                 {
6599                     ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6600                             resource, device->stateBlock, i);
6601                     device->stateBlock->streamSource[i] = NULL;
6602                 }
6603
6604                 if (device->updateStateBlock != device->stateBlock
6605                         && device->updateStateBlock->streamSource[i] == (IWineD3DBuffer *)resource)
6606                 {
6607                     ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6608                             resource, device->updateStateBlock, i);
6609                     device->updateStateBlock->streamSource[i] = NULL;
6610                 }
6611
6612             }
6613
6614             if (device->stateBlock && device->stateBlock->pIndexData == (IWineD3DBuffer *)resource)
6615             {
6616                 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6617                         resource, device->stateBlock);
6618                 device->stateBlock->pIndexData =  NULL;
6619             }
6620
6621             if (device->updateStateBlock != device->stateBlock
6622                     && device->updateStateBlock->pIndexData == (IWineD3DBuffer *)resource)
6623             {
6624                 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6625                         resource, device->updateStateBlock);
6626                 device->updateStateBlock->pIndexData =  NULL;
6627             }
6628             break;
6629
6630         default:
6631             break;
6632     }
6633
6634     /* Remove the resource from the resourceStore */
6635     device_resource_remove(device, resource);
6636
6637     TRACE("Resource released.\n");
6638 }
6639
6640 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
6641     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6642     IWineD3DResourceImpl *resource, *cursor;
6643     HRESULT ret;
6644     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
6645
6646     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6647         TRACE("enumerating resource %p\n", resource);
6648         IWineD3DResource_AddRef((IWineD3DResource *) resource);
6649         ret = pCallback((IWineD3DResource *) resource, pData);
6650         if(ret == S_FALSE) {
6651             TRACE("Canceling enumeration\n");
6652             break;
6653         }
6654     }
6655     return WINED3D_OK;
6656 }
6657
6658 static HRESULT WINAPI IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice *iface, HDC dc, IWineD3DSurface **surface)
6659 {
6660     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6661     IWineD3DResourceImpl *resource;
6662
6663     LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry)
6664     {
6665         WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource);
6666         if (type == WINED3DRTYPE_SURFACE)
6667         {
6668             if (((IWineD3DSurfaceImpl *)resource)->hDC == dc)
6669             {
6670                 TRACE("Found surface %p for dc %p.\n", resource, dc);
6671                 *surface = (IWineD3DSurface *)resource;
6672                 return WINED3D_OK;
6673             }
6674         }
6675     }
6676
6677     return WINED3DERR_INVALIDCALL;
6678 }
6679
6680 /**********************************************************
6681  * IWineD3DDevice VTbl follows
6682  **********************************************************/
6683
6684 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6685 {
6686     /*** IUnknown methods ***/
6687     IWineD3DDeviceImpl_QueryInterface,
6688     IWineD3DDeviceImpl_AddRef,
6689     IWineD3DDeviceImpl_Release,
6690     /*** IWineD3DDevice methods ***/
6691     IWineD3DDeviceImpl_GetParent,
6692     /*** Creation methods**/
6693     IWineD3DDeviceImpl_CreateBuffer,
6694     IWineD3DDeviceImpl_CreateVertexBuffer,
6695     IWineD3DDeviceImpl_CreateIndexBuffer,
6696     IWineD3DDeviceImpl_CreateStateBlock,
6697     IWineD3DDeviceImpl_CreateSurface,
6698     IWineD3DDeviceImpl_CreateRendertargetView,
6699     IWineD3DDeviceImpl_CreateTexture,
6700     IWineD3DDeviceImpl_CreateVolumeTexture,
6701     IWineD3DDeviceImpl_CreateVolume,
6702     IWineD3DDeviceImpl_CreateCubeTexture,
6703     IWineD3DDeviceImpl_CreateQuery,
6704     IWineD3DDeviceImpl_CreateSwapChain,
6705     IWineD3DDeviceImpl_CreateVertexDeclaration,
6706     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
6707     IWineD3DDeviceImpl_CreateVertexShader,
6708     IWineD3DDeviceImpl_CreateGeometryShader,
6709     IWineD3DDeviceImpl_CreatePixelShader,
6710     IWineD3DDeviceImpl_CreatePalette,
6711     /*** Odd functions **/
6712     IWineD3DDeviceImpl_Init3D,
6713     IWineD3DDeviceImpl_InitGDI,
6714     IWineD3DDeviceImpl_Uninit3D,
6715     IWineD3DDeviceImpl_UninitGDI,
6716     IWineD3DDeviceImpl_SetMultithreaded,
6717     IWineD3DDeviceImpl_EvictManagedResources,
6718     IWineD3DDeviceImpl_GetAvailableTextureMem,
6719     IWineD3DDeviceImpl_GetBackBuffer,
6720     IWineD3DDeviceImpl_GetCreationParameters,
6721     IWineD3DDeviceImpl_GetDeviceCaps,
6722     IWineD3DDeviceImpl_GetDirect3D,
6723     IWineD3DDeviceImpl_GetDisplayMode,
6724     IWineD3DDeviceImpl_SetDisplayMode,
6725     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6726     IWineD3DDeviceImpl_GetRasterStatus,
6727     IWineD3DDeviceImpl_GetSwapChain,
6728     IWineD3DDeviceImpl_Reset,
6729     IWineD3DDeviceImpl_SetDialogBoxMode,
6730     IWineD3DDeviceImpl_SetCursorProperties,
6731     IWineD3DDeviceImpl_SetCursorPosition,
6732     IWineD3DDeviceImpl_ShowCursor,
6733     /*** Getters and setters **/
6734     IWineD3DDeviceImpl_SetClipPlane,
6735     IWineD3DDeviceImpl_GetClipPlane,
6736     IWineD3DDeviceImpl_SetClipStatus,
6737     IWineD3DDeviceImpl_GetClipStatus,
6738     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6739     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6740     IWineD3DDeviceImpl_SetDepthStencilSurface,
6741     IWineD3DDeviceImpl_GetDepthStencilSurface,
6742     IWineD3DDeviceImpl_SetGammaRamp,
6743     IWineD3DDeviceImpl_GetGammaRamp,
6744     IWineD3DDeviceImpl_SetIndexBuffer,
6745     IWineD3DDeviceImpl_GetIndexBuffer,
6746     IWineD3DDeviceImpl_SetBaseVertexIndex,
6747     IWineD3DDeviceImpl_GetBaseVertexIndex,
6748     IWineD3DDeviceImpl_SetLight,
6749     IWineD3DDeviceImpl_GetLight,
6750     IWineD3DDeviceImpl_SetLightEnable,
6751     IWineD3DDeviceImpl_GetLightEnable,
6752     IWineD3DDeviceImpl_SetMaterial,
6753     IWineD3DDeviceImpl_GetMaterial,
6754     IWineD3DDeviceImpl_SetNPatchMode,
6755     IWineD3DDeviceImpl_GetNPatchMode,
6756     IWineD3DDeviceImpl_SetPaletteEntries,
6757     IWineD3DDeviceImpl_GetPaletteEntries,
6758     IWineD3DDeviceImpl_SetPixelShader,
6759     IWineD3DDeviceImpl_GetPixelShader,
6760     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6761     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6762     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6763     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6764     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6765     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6766     IWineD3DDeviceImpl_SetRenderState,
6767     IWineD3DDeviceImpl_GetRenderState,
6768     IWineD3DDeviceImpl_SetRenderTarget,
6769     IWineD3DDeviceImpl_GetRenderTarget,
6770     IWineD3DDeviceImpl_SetFrontBackBuffers,
6771     IWineD3DDeviceImpl_SetSamplerState,
6772     IWineD3DDeviceImpl_GetSamplerState,
6773     IWineD3DDeviceImpl_SetScissorRect,
6774     IWineD3DDeviceImpl_GetScissorRect,
6775     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6776     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6777     IWineD3DDeviceImpl_SetStreamSource,
6778     IWineD3DDeviceImpl_GetStreamSource,
6779     IWineD3DDeviceImpl_SetStreamSourceFreq,
6780     IWineD3DDeviceImpl_GetStreamSourceFreq,
6781     IWineD3DDeviceImpl_SetTexture,
6782     IWineD3DDeviceImpl_GetTexture,
6783     IWineD3DDeviceImpl_SetTextureStageState,
6784     IWineD3DDeviceImpl_GetTextureStageState,
6785     IWineD3DDeviceImpl_SetTransform,
6786     IWineD3DDeviceImpl_GetTransform,
6787     IWineD3DDeviceImpl_SetVertexDeclaration,
6788     IWineD3DDeviceImpl_GetVertexDeclaration,
6789     IWineD3DDeviceImpl_SetVertexShader,
6790     IWineD3DDeviceImpl_GetVertexShader,
6791     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6792     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6793     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6794     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6795     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6796     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6797     IWineD3DDeviceImpl_SetViewport,
6798     IWineD3DDeviceImpl_GetViewport,
6799     IWineD3DDeviceImpl_MultiplyTransform,
6800     IWineD3DDeviceImpl_ValidateDevice,
6801     IWineD3DDeviceImpl_ProcessVertices,
6802     /*** State block ***/
6803     IWineD3DDeviceImpl_BeginStateBlock,
6804     IWineD3DDeviceImpl_EndStateBlock,
6805     /*** Scene management ***/
6806     IWineD3DDeviceImpl_BeginScene,
6807     IWineD3DDeviceImpl_EndScene,
6808     IWineD3DDeviceImpl_Present,
6809     IWineD3DDeviceImpl_Clear,
6810     IWineD3DDeviceImpl_ClearRendertargetView,
6811     /*** Drawing ***/
6812     IWineD3DDeviceImpl_SetPrimitiveType,
6813     IWineD3DDeviceImpl_GetPrimitiveType,
6814     IWineD3DDeviceImpl_DrawPrimitive,
6815     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6816     IWineD3DDeviceImpl_DrawPrimitiveUP,
6817     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6818     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6819     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
6820     IWineD3DDeviceImpl_DrawRectPatch,
6821     IWineD3DDeviceImpl_DrawTriPatch,
6822     IWineD3DDeviceImpl_DeletePatch,
6823     IWineD3DDeviceImpl_ColorFill,
6824     IWineD3DDeviceImpl_UpdateTexture,
6825     IWineD3DDeviceImpl_UpdateSurface,
6826     IWineD3DDeviceImpl_GetFrontBufferData,
6827     /*** object tracking ***/
6828     IWineD3DDeviceImpl_EnumResources,
6829     IWineD3DDeviceImpl_GetSurfaceFromDC,
6830     IWineD3DDeviceImpl_AcquireFocusWindow,
6831     IWineD3DDeviceImpl_ReleaseFocusWindow,
6832 };
6833
6834 HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d,
6835         UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags,
6836         IUnknown *parent, IWineD3DDeviceParent *device_parent)
6837 {
6838     struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
6839     const struct fragment_pipeline *fragment_pipeline;
6840     struct shader_caps shader_caps;
6841     struct fragment_caps ffp_caps;
6842     WINED3DDISPLAYMODE mode;
6843     unsigned int i;
6844     HRESULT hr;
6845
6846     device->lpVtbl = &IWineD3DDevice_Vtbl;
6847     device->ref = 1;
6848     device->wined3d = (IWineD3D *)wined3d;
6849     IWineD3D_AddRef(device->wined3d);
6850     device->adapter = wined3d->adapter_count ? adapter : NULL;
6851     device->parent  = parent;
6852     device->device_parent = device_parent;
6853     list_init(&device->resources);
6854     list_init(&device->shaders);
6855
6856     device->surface_alignment = wined3d->dxVersion == 7 ? DDRAW_PITCH_ALIGNMENT : D3D8_PITCH_ALIGNMENT;
6857     device->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
6858
6859     /* Get the initial screen setup for ddraw. */
6860     hr = IWineD3D_GetAdapterDisplayMode((IWineD3D *)wined3d, adapter_idx, &mode);
6861     if (FAILED(hr))
6862     {
6863         ERR("Failed to get the adapter's display mode, hr %#x.\n", hr);
6864         IWineD3D_Release(device->wined3d);
6865         return hr;
6866     }
6867     device->ddraw_width = mode.Width;
6868     device->ddraw_height = mode.Height;
6869     device->ddraw_format = mode.Format;
6870
6871     /* Save the creation parameters. */
6872     device->createParms.AdapterOrdinal = adapter_idx;
6873     device->createParms.DeviceType = device_type;
6874     device->createParms.hFocusWindow = focus_window;
6875     device->createParms.BehaviorFlags = flags;
6876
6877     device->devType = device_type;
6878     for (i = 0; i < PATCHMAP_SIZE; ++i) list_init(&device->patches[i]);
6879
6880     select_shader_mode(&adapter->gl_info, &device->ps_selected_mode, &device->vs_selected_mode);
6881     device->shader_backend = adapter->shader_backend;
6882
6883     if (device->shader_backend)
6884     {
6885         device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
6886         device->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
6887         device->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
6888         device->vs_clipping = shader_caps.VSClipping;
6889     }
6890     fragment_pipeline = adapter->fragment_pipe;
6891     device->frag_pipe = fragment_pipeline;
6892     if (fragment_pipeline)
6893     {
6894         fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
6895         device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
6896
6897         hr = compile_state_table(device->StateTable, device->multistate_funcs, &adapter->gl_info,
6898                                  ffp_vertexstate_template, fragment_pipeline, misc_state_template);
6899         if (FAILED(hr))
6900         {
6901             ERR("Failed to compile state table, hr %#x.\n", hr);
6902             IWineD3D_Release(device->wined3d);
6903             return hr;
6904         }
6905     }
6906     device->blitter = adapter->blitter;
6907
6908     return WINED3D_OK;
6909 }
6910
6911
6912 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6913     DWORD rep = This->StateTable[state].representative;
6914     struct wined3d_context *context;
6915     DWORD idx;
6916     BYTE shift;
6917     UINT i;
6918
6919     for(i = 0; i < This->numContexts; i++) {
6920         context = This->contexts[i];
6921         if(isStateDirty(context, rep)) continue;
6922
6923         context->dirtyArray[context->numDirtyEntries++] = rep;
6924         idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
6925         shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
6926         context->isStateDirty[idx] |= (1 << shift);
6927     }
6928 }
6929
6930 void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height)
6931 {
6932     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
6933     *width = context->current_rt->pow2Width;
6934     *height = context->current_rt->pow2Height;
6935 }
6936
6937 void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height)
6938 {
6939     IWineD3DSwapChainImpl *swapchain = context->swapchain;
6940     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
6941      * current context's drawable, which is the size of the back buffer of the swapchain
6942      * the active context belongs to. */
6943     *width = swapchain->presentParms.BackBufferWidth;
6944     *height = swapchain->presentParms.BackBufferHeight;
6945 }
6946
6947 LRESULT device_process_message(IWineD3DDeviceImpl *device, HWND window,
6948         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
6949 {
6950     if (device->filter_messages)
6951     {
6952         TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
6953                 window, message, wparam, lparam);
6954         return DefWindowProcW(window, message, wparam, lparam);
6955     }
6956
6957     if (message == WM_DESTROY)
6958     {
6959         TRACE("unregister window %p.\n", window);
6960         wined3d_unregister_window(window);
6961
6962         if (device->focus_window == window) device->focus_window = NULL;
6963         else ERR("Window %p is not the focus window for device %p.\n", window, device);
6964     }
6965
6966     return CallWindowProcW(proc, window, message, wparam, lparam);
6967 }