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