wined3d: Getting the current vertex shader should never fail.
[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 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3608     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3609
3610     if (NULL == ppShader) {
3611         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3612         return WINED3DERR_INVALIDCALL;
3613     }
3614
3615     *ppShader =  This->stateBlock->pixelShader;
3616     if (NULL != *ppShader) {
3617         IWineD3DPixelShader_AddRef(*ppShader);
3618     }
3619     TRACE("(%p) : returning %p\n", This, *ppShader);
3620     return WINED3D_OK;
3621 }
3622
3623 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3624     IWineD3DDevice *iface,
3625     UINT start,
3626     CONST BOOL *srcData,
3627     UINT count) {
3628
3629     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3630     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3631
3632     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3633             iface, srcData, start, count);
3634
3635     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3636
3637     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3638     for (i = 0; i < cnt; i++)
3639         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3640
3641     for (i = start; i < cnt + start; ++i) {
3642         This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
3643     }
3644
3645     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3646
3647     return WINED3D_OK;
3648 }
3649
3650 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3651     IWineD3DDevice *iface,
3652     UINT start,
3653     BOOL *dstData,
3654     UINT count) {
3655
3656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3657     int cnt = min(count, MAX_CONST_B - start);
3658
3659     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3660             iface, dstData, start, count);
3661
3662     if (dstData == NULL || cnt < 0)
3663         return WINED3DERR_INVALIDCALL;
3664
3665     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3666     return WINED3D_OK;
3667 }
3668
3669 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3670     IWineD3DDevice *iface,
3671     UINT start,
3672     CONST int *srcData,
3673     UINT count) {
3674
3675     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3676     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3677
3678     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3679             iface, srcData, start, count);
3680
3681     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3682
3683     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3684     for (i = 0; i < cnt; i++)
3685         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3686            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3687
3688     for (i = start; i < cnt + start; ++i) {
3689         This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
3690     }
3691
3692     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3693
3694     return WINED3D_OK;
3695 }
3696
3697 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3698     IWineD3DDevice *iface,
3699     UINT start,
3700     int *dstData,
3701     UINT count) {
3702
3703     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3704     int cnt = min(count, MAX_CONST_I - start);
3705
3706     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3707             iface, dstData, start, count);
3708
3709     if (dstData == NULL || cnt < 0)
3710         return WINED3DERR_INVALIDCALL;
3711
3712     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3713     return WINED3D_OK;
3714 }
3715
3716 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3717     IWineD3DDevice *iface,
3718     UINT start,
3719     CONST float *srcData,
3720     UINT count) {
3721
3722     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3723     UINT i;
3724
3725     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3726             iface, srcData, start, count);
3727
3728     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3729     if (srcData == NULL || start + count > This->d3d_pshader_constantF || start > This->d3d_pshader_constantF)
3730         return WINED3DERR_INVALIDCALL;
3731
3732     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3733     if(TRACE_ON(d3d)) {
3734         for (i = 0; i < count; i++)
3735             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3736                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3737     }
3738
3739     if (!This->isRecordingState)
3740     {
3741         This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
3742         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3743     }
3744
3745     memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
3746             sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
3747
3748     return WINED3D_OK;
3749 }
3750
3751 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3752     IWineD3DDevice *iface,
3753     UINT start,
3754     float *dstData,
3755     UINT count) {
3756
3757     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3758     int cnt = min(count, This->d3d_pshader_constantF - start);
3759
3760     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3761             iface, dstData, start, count);
3762
3763     if (dstData == NULL || cnt < 0)
3764         return WINED3DERR_INVALIDCALL;
3765
3766     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3767     return WINED3D_OK;
3768 }
3769
3770 /* Context activation is done by the caller. */
3771 /* Do not call while under the GL lock. */
3772 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3773 static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount,
3774         const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD dwFlags,
3775         DWORD DestFVF)
3776 {
3777     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
3778     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3779     unsigned int i;
3780     WINED3DVIEWPORT vp;
3781     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3782     BOOL doClip;
3783     DWORD numTextures;
3784
3785     if (stream_info->use_map & (1 << WINED3D_FFP_NORMAL))
3786     {
3787         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3788     }
3789
3790     if (!(stream_info->use_map & (1 << WINED3D_FFP_POSITION)))
3791     {
3792         ERR("Source has no position mask\n");
3793         return WINED3DERR_INVALIDCALL;
3794     }
3795
3796     if (!dest->resource.allocatedMemory)
3797         buffer_get_sysmem(dest, gl_info);
3798
3799     /* Get a pointer into the destination vbo(create one if none exists) and
3800      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3801      */
3802     if (!dest->buffer_object && gl_info->supported[ARB_VERTEX_BUFFER_OBJECT])
3803     {
3804         dest->flags |= WINED3D_BUFFER_CREATEBO;
3805         IWineD3DBuffer_PreLoad((IWineD3DBuffer *)dest);
3806     }
3807
3808     if (dest->buffer_object)
3809     {
3810         unsigned char extrabytes = 0;
3811         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3812          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3813          * this may write 4 extra bytes beyond the area that should be written
3814          */
3815         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
3816         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
3817         if(!dest_conv_addr) {
3818             ERR("Out of memory\n");
3819             /* Continue without storing converted vertices */
3820         }
3821         dest_conv = dest_conv_addr;
3822     }
3823
3824     /* Should I clip?
3825      * a) WINED3DRS_CLIPPING is enabled
3826      * b) WINED3DVOP_CLIP is passed
3827      */
3828     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3829         static BOOL warned = FALSE;
3830         /*
3831          * The clipping code is not quite correct. Some things need
3832          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3833          * so disable clipping for now.
3834          * (The graphics in Half-Life are broken, and my processvertices
3835          *  test crashes with IDirect3DDevice3)
3836         doClip = TRUE;
3837          */
3838         doClip = FALSE;
3839         if(!warned) {
3840            warned = TRUE;
3841            FIXME("Clipping is broken and disabled for now\n");
3842         }
3843     } else doClip = FALSE;
3844     dest_ptr = ((char *)buffer_get_sysmem(dest, gl_info)) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3845
3846     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3847                                  WINED3DTS_VIEW,
3848                                  &view_mat);
3849     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3850                                  WINED3DTS_PROJECTION,
3851                                  &proj_mat);
3852     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3853                                  WINED3DTS_WORLDMATRIX(0),
3854                                  &world_mat);
3855
3856     TRACE("View mat:\n");
3857     TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14);
3858     TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24);
3859     TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34);
3860     TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44);
3861
3862     TRACE("Proj mat:\n");
3863     TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14);
3864     TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24);
3865     TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34);
3866     TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44);
3867
3868     TRACE("World mat:\n");
3869     TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14);
3870     TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24);
3871     TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34);
3872     TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44);
3873
3874     /* Get the viewport */
3875     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3876     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3877           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3878
3879     multiply_matrix(&mat,&view_mat,&world_mat);
3880     multiply_matrix(&mat,&proj_mat,&mat);
3881
3882     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3883
3884     for (i = 0; i < dwCount; i+= 1) {
3885         unsigned int tex_index;
3886
3887         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3888              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3889             /* The position first */
3890             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
3891             const float *p = (const float *)(element->data + i * element->stride);
3892             float x, y, z, rhw;
3893             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3894
3895             /* Multiplication with world, view and projection matrix */
3896             x =   (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0f * mat.u.s._41);
3897             y =   (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0f * mat.u.s._42);
3898             z =   (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0f * mat.u.s._43);
3899             rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0f * mat.u.s._44);
3900
3901             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3902
3903             /* WARNING: The following things are taken from d3d7 and were not yet checked
3904              * against d3d8 or d3d9!
3905              */
3906
3907             /* Clipping conditions: From msdn
3908              *
3909              * A vertex is clipped if it does not match the following requirements
3910              * -rhw < x <= rhw
3911              * -rhw < y <= rhw
3912              *    0 < z <= rhw
3913              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3914              *
3915              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3916              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3917              *
3918              */
3919
3920             if( !doClip ||
3921                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3922                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3923                   ( rhw > eps ) ) ) {
3924
3925                 /* "Normal" viewport transformation (not clipped)
3926                  * 1) The values are divided by rhw
3927                  * 2) The y axis is negative, so multiply it with -1
3928                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3929                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3930                  * 4) Multiply x with Width/2 and add Width/2
3931                  * 5) The same for the height
3932                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3933                  *    The minimum Z value to z
3934                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3935                  *
3936                  * Well, basically it's simply a linear transformation into viewport
3937                  * coordinates
3938                  */
3939
3940                 x /= rhw;
3941                 y /= rhw;
3942                 z /= rhw;
3943
3944                 y *= -1;
3945
3946                 x *= vp.Width / 2;
3947                 y *= vp.Height / 2;
3948                 z *= vp.MaxZ - vp.MinZ;
3949
3950                 x += vp.Width / 2 + vp.X;
3951                 y += vp.Height / 2 + vp.Y;
3952                 z += vp.MinZ;
3953
3954                 rhw = 1 / rhw;
3955             } else {
3956                 /* That vertex got clipped
3957                  * Contrary to OpenGL it is not dropped completely, it just
3958                  * undergoes a different calculation.
3959                  */
3960                 TRACE("Vertex got clipped\n");
3961                 x += rhw;
3962                 y += rhw;
3963
3964                 x  /= 2;
3965                 y  /= 2;
3966
3967                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3968                  * outside of the main vertex buffer memory. That needs some more
3969                  * investigation...
3970                  */
3971             }
3972
3973             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3974
3975
3976             ( (float *) dest_ptr)[0] = x;
3977             ( (float *) dest_ptr)[1] = y;
3978             ( (float *) dest_ptr)[2] = z;
3979             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3980
3981             dest_ptr += 3 * sizeof(float);
3982
3983             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3984                 dest_ptr += sizeof(float);
3985             }
3986
3987             if(dest_conv) {
3988                 float w = 1 / rhw;
3989                 ( (float *) dest_conv)[0] = x * w;
3990                 ( (float *) dest_conv)[1] = y * w;
3991                 ( (float *) dest_conv)[2] = z * w;
3992                 ( (float *) dest_conv)[3] = w;
3993
3994                 dest_conv += 3 * sizeof(float);
3995
3996                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3997                     dest_conv += sizeof(float);
3998                 }
3999             }
4000         }
4001         if (DestFVF & WINED3DFVF_PSIZE) {
4002             dest_ptr += sizeof(DWORD);
4003             if(dest_conv) dest_conv += sizeof(DWORD);
4004         }
4005         if (DestFVF & WINED3DFVF_NORMAL) {
4006             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
4007             const float *normal = (const float *)(element->data + i * element->stride);
4008             /* AFAIK this should go into the lighting information */
4009             FIXME("Didn't expect the destination to have a normal\n");
4010             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4011             if(dest_conv) {
4012                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4013             }
4014         }
4015
4016         if (DestFVF & WINED3DFVF_DIFFUSE) {
4017             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
4018             const DWORD *color_d = (const DWORD *)(element->data + i * element->stride);
4019             if (!(stream_info->use_map & (1 << WINED3D_FFP_DIFFUSE)))
4020             {
4021                 static BOOL warned = FALSE;
4022
4023                 if(!warned) {
4024                     ERR("No diffuse color in source, but destination has one\n");
4025                     warned = TRUE;
4026                 }
4027
4028                 *( (DWORD *) dest_ptr) = 0xffffffff;
4029                 dest_ptr += sizeof(DWORD);
4030
4031                 if(dest_conv) {
4032                     *( (DWORD *) dest_conv) = 0xffffffff;
4033                     dest_conv += sizeof(DWORD);
4034                 }
4035             }
4036             else {
4037                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4038                 if(dest_conv) {
4039                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4040                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4041                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4042                     dest_conv += sizeof(DWORD);
4043                 }
4044             }
4045         }
4046
4047         if (DestFVF & WINED3DFVF_SPECULAR)
4048         {
4049             /* What's the color value in the feedback buffer? */
4050             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
4051             const DWORD *color_s = (const DWORD *)(element->data + i * element->stride);
4052             if (!(stream_info->use_map & (1 << WINED3D_FFP_SPECULAR)))
4053             {
4054                 static BOOL warned = FALSE;
4055
4056                 if(!warned) {
4057                     ERR("No specular color in source, but destination has one\n");
4058                     warned = TRUE;
4059                 }
4060
4061                 *( (DWORD *) dest_ptr) = 0xFF000000;
4062                 dest_ptr += sizeof(DWORD);
4063
4064                 if(dest_conv) {
4065                     *( (DWORD *) dest_conv) = 0xFF000000;
4066                     dest_conv += sizeof(DWORD);
4067                 }
4068             }
4069             else {
4070                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4071                 if(dest_conv) {
4072                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4073                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4074                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4075                     dest_conv += sizeof(DWORD);
4076                 }
4077             }
4078         }
4079
4080         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4081             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
4082             const float *tex_coord = (const float *)(element->data + i * element->stride);
4083             if (!(stream_info->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + tex_index))))
4084             {
4085                 ERR("No source texture, but destination requests one\n");
4086                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4087                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4088             }
4089             else {
4090                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4091                 if(dest_conv) {
4092                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4093                 }
4094             }
4095         }
4096     }
4097
4098     if (dest_conv)
4099     {
4100         ENTER_GL();
4101
4102         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->buffer_object));
4103         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4104         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
4105                                       dwCount * get_flexible_vertex_size(DestFVF),
4106                                       dest_conv_addr));
4107         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4108
4109         LEAVE_GL();
4110
4111         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
4112     }
4113
4114     return WINED3D_OK;
4115 }
4116 #undef copy_and_next
4117
4118 /* Do not call while under the GL lock. */
4119 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex,
4120         UINT VertexCount, IWineD3DBuffer *pDestBuffer, IWineD3DVertexDeclaration *pVertexDecl, DWORD Flags,
4121         DWORD DestFVF)
4122 {
4123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4124     struct wined3d_stream_info stream_info;
4125     const struct wined3d_gl_info *gl_info;
4126     struct wined3d_context *context;
4127     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
4128     HRESULT hr;
4129
4130     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4131
4132     if(pVertexDecl) {
4133         ERR("Output vertex declaration not implemented yet\n");
4134     }
4135
4136     /* Need any context to write to the vbo. */
4137     context = context_acquire(This, NULL);
4138     gl_info = context->gl_info;
4139
4140     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4141      * control the streamIsUP flag, thus restore it afterwards.
4142      */
4143     This->stateBlock->streamIsUP = FALSE;
4144     device_stream_info_from_declaration(This, FALSE, &stream_info, &vbo);
4145     This->stateBlock->streamIsUP = streamWasUP;
4146
4147     if(vbo || SrcStartIndex) {
4148         unsigned int i;
4149         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4150          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4151          *
4152          * Also get the start index in, but only loop over all elements if there's something to add at all.
4153          */
4154         for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
4155         {
4156             struct wined3d_stream_info_element *e;
4157
4158             if (!(stream_info.use_map & (1 << i))) continue;
4159
4160             e = &stream_info.elements[i];
4161             if (e->buffer_object)
4162             {
4163                 struct wined3d_buffer *vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx];
4164                 e->buffer_object = 0;
4165                 e->data = (BYTE *)((ULONG_PTR)e->data + (ULONG_PTR)buffer_get_sysmem(vb, gl_info));
4166                 ENTER_GL();
4167                 GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
4168                 vb->buffer_object = 0;
4169                 LEAVE_GL();
4170             }
4171             if (e->data) e->data += e->stride * SrcStartIndex;
4172         }
4173     }
4174
4175     hr = process_vertices_strided(This, DestIndex, VertexCount, &stream_info,
4176             (struct wined3d_buffer *)pDestBuffer, Flags, DestFVF);
4177
4178     context_release(context);
4179
4180     return hr;
4181 }
4182
4183 /*****
4184  * Get / Set Texture Stage States
4185  * TODO: Verify against dx9 definitions
4186  *****/
4187 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4188     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4189     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4190     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4191
4192     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4193
4194     if (Stage >= gl_info->limits.texture_stages)
4195     {
4196         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
4197                 Stage, gl_info->limits.texture_stages - 1);
4198         return WINED3D_OK;
4199     }
4200
4201     This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
4202     This->updateStateBlock->textureState[Stage][Type]         = Value;
4203
4204     if (This->isRecordingState) {
4205         TRACE("Recording... not performing anything\n");
4206         return WINED3D_OK;
4207     }
4208
4209     /* Checked after the assignments to allow proper stateblock recording */
4210     if(oldValue == Value) {
4211         TRACE("App is setting the old value over, nothing to do\n");
4212         return WINED3D_OK;
4213     }
4214
4215     if(Stage > This->stateBlock->lowest_disabled_stage &&
4216        This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4217         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4218          * Changes in other states are important on disabled stages too
4219          */
4220         return WINED3D_OK;
4221     }
4222
4223     if(Type == WINED3DTSS_COLOROP) {
4224         unsigned int i;
4225
4226         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4227             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4228              * they have to be disabled
4229              *
4230              * The current stage is dirtified below.
4231              */
4232             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4233                 TRACE("Additionally dirtifying stage %u\n", i);
4234                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4235             }
4236             This->stateBlock->lowest_disabled_stage = Stage;
4237             TRACE("New lowest disabled: %u\n", Stage);
4238         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4239             /* Previously disabled stage enabled. Stages above it may need enabling
4240              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4241              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4242              *
4243              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4244              */
4245
4246             for (i = Stage + 1; i < This->adapter->gl_info.limits.texture_stages; ++i)
4247             {
4248                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4249                     break;
4250                 }
4251                 TRACE("Additionally dirtifying stage %u due to enable\n", i);
4252                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4253             }
4254             This->stateBlock->lowest_disabled_stage = i;
4255             TRACE("New lowest disabled: %u\n", i);
4256         }
4257     }
4258
4259     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4260
4261     return WINED3D_OK;
4262 }
4263
4264 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4265     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4266     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4267     *pValue = This->updateStateBlock->textureState[Stage][Type];
4268     return WINED3D_OK;
4269 }
4270
4271 /*****
4272  * Get / Set Texture
4273  *****/
4274 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface,
4275         DWORD stage, IWineD3DBaseTexture *texture)
4276 {
4277     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4278     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4279     IWineD3DBaseTexture *prev;
4280
4281     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4282
4283     if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3)
4284         stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4285
4286     /* Windows accepts overflowing this array... we do not. */
4287     if (stage >= sizeof(This->stateBlock->textures) / sizeof(*This->stateBlock->textures))
4288     {
4289         WARN("Ignoring invalid stage %u.\n", stage);
4290         return WINED3D_OK;
4291     }
4292
4293     /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4294     if (texture && ((IWineD3DTextureImpl *)texture)->resource.pool == WINED3DPOOL_SCRATCH)
4295     {
4296         WARN("Rejecting attempt to set scratch texture.\n");
4297         return WINED3DERR_INVALIDCALL;
4298     }
4299
4300     This->updateStateBlock->changed.textures |= 1 << stage;
4301
4302     prev = This->updateStateBlock->textures[stage];
4303     TRACE("Previous texture %p.\n", prev);
4304
4305     if (texture == prev)
4306     {
4307         TRACE("App is setting the same texture again, nothing to do.\n");
4308         return WINED3D_OK;
4309     }
4310
4311     TRACE("Setting new texture to %p.\n", texture);
4312     This->updateStateBlock->textures[stage] = texture;
4313
4314     if (This->isRecordingState)
4315     {
4316         TRACE("Recording... not performing anything\n");
4317
4318         if (texture) IWineD3DBaseTexture_AddRef(texture);
4319         if (prev) IWineD3DBaseTexture_Release(prev);
4320
4321         return WINED3D_OK;
4322     }
4323
4324     if (texture)
4325     {
4326         IWineD3DBaseTextureImpl *t = (IWineD3DBaseTextureImpl *)texture;
4327         LONG bind_count = InterlockedIncrement(&t->baseTexture.bindCount);
4328         UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
4329
4330         IWineD3DBaseTexture_AddRef(texture);
4331
4332         if (!prev || dimensions != IWineD3DBaseTexture_GetTextureDimensions(prev))
4333         {
4334             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
4335         }
4336
4337         if (!prev && stage < gl_info->limits.texture_stages)
4338         {
4339             /* The source arguments for color and alpha ops have different
4340              * meanings when a NULL texture is bound, so the COLOROP and
4341              * ALPHAOP have to be dirtified. */
4342             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_COLOROP));
4343             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_ALPHAOP));
4344         }
4345
4346         if (bind_count == 1) t->baseTexture.sampler = stage;
4347     }
4348
4349     if (prev)
4350     {
4351         IWineD3DBaseTextureImpl *t = (IWineD3DBaseTextureImpl *)prev;
4352         LONG bind_count = InterlockedDecrement(&t->baseTexture.bindCount);
4353
4354         IWineD3DBaseTexture_Release(prev);
4355
4356         if (!texture && stage < gl_info->limits.texture_stages)
4357         {
4358             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_COLOROP));
4359             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_ALPHAOP));
4360         }
4361
4362         if (bind_count && t->baseTexture.sampler == stage)
4363         {
4364             unsigned int i;
4365
4366             /* Search for other stages the texture is bound to. Shouldn't
4367              * happen if applications bind textures to a single stage only. */
4368             TRACE("Searching for other stages the texture is bound to.\n");
4369             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
4370             {
4371                 if (This->updateStateBlock->textures[i] == prev)
4372                 {
4373                     TRACE("Texture is also bound to stage %u.\n", i);
4374                     t->baseTexture.sampler = i;
4375                     break;
4376                 }
4377             }
4378         }
4379     }
4380
4381     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(stage));
4382
4383     return WINED3D_OK;
4384 }
4385
4386 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4387     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4388
4389     TRACE("(%p) : Stage %#x, ppTexture %p\n", This, Stage, ppTexture);
4390
4391     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4392         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4393     }
4394
4395     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4396         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4397         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4398     }
4399
4400     *ppTexture=This->stateBlock->textures[Stage];
4401     if (*ppTexture)
4402         IWineD3DBaseTexture_AddRef(*ppTexture);
4403
4404     TRACE("(%p) : Returning %p\n", This, *ppTexture);
4405
4406     return WINED3D_OK;
4407 }
4408
4409 /*****
4410  * Get Back Buffer
4411  *****/
4412 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT swapchain_idx,
4413         UINT backbuffer_idx, WINED3DBACKBUFFER_TYPE backbuffer_type, IWineD3DSurface **backbuffer)
4414 {
4415     IWineD3DSwapChain *swapchain;
4416     HRESULT hr;
4417
4418     TRACE("iface %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
4419             iface, swapchain_idx, backbuffer_idx, backbuffer_type, backbuffer);
4420
4421     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
4422     if (FAILED(hr))
4423     {
4424         WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx, hr);
4425         return hr;
4426     }
4427
4428     hr = IWineD3DSwapChain_GetBackBuffer(swapchain, backbuffer_idx, backbuffer_type, backbuffer);
4429     IWineD3DSwapChain_Release(swapchain);
4430     if (FAILED(hr))
4431     {
4432         WARN("Failed to get backbuffer %u, hr %#x.\n", backbuffer_idx, hr);
4433         return hr;
4434     }
4435
4436     return WINED3D_OK;
4437 }
4438
4439 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4440     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4441     WARN("(%p) : stub, calling idirect3d for now\n", This);
4442     return IWineD3D_GetDeviceCaps(This->wined3d, This->adapter->ordinal, This->devType, pCaps);
4443 }
4444
4445 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4446     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4447     IWineD3DSwapChain *swapChain;
4448     HRESULT hr;
4449
4450     if(iSwapChain > 0) {
4451         hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4452         if (hr == WINED3D_OK) {
4453             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4454             IWineD3DSwapChain_Release(swapChain);
4455         } else {
4456             FIXME("(%p) Error getting display mode\n", This);
4457         }
4458     } else {
4459         /* Don't read the real display mode,
4460            but return the stored mode instead. X11 can't change the color
4461            depth, and some apps are pretty angry if they SetDisplayMode from
4462            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4463
4464            Also don't relay to the swapchain because with ddraw it's possible
4465            that there isn't a swapchain at all */
4466         pMode->Width = This->ddraw_width;
4467         pMode->Height = This->ddraw_height;
4468         pMode->Format = This->ddraw_format;
4469         pMode->RefreshRate = 0;
4470         hr = WINED3D_OK;
4471     }
4472
4473     return hr;
4474 }
4475
4476 /*****
4477  * Stateblock related functions
4478  *****/
4479
4480 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4482     IWineD3DStateBlock *stateblock;
4483     HRESULT hr;
4484
4485     TRACE("(%p)\n", This);
4486
4487     if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
4488
4489     hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock);
4490     if (FAILED(hr)) return hr;
4491
4492     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4493     This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
4494     This->isRecordingState = TRUE;
4495
4496     TRACE("(%p) recording stateblock %p\n", This, stateblock);
4497
4498     return WINED3D_OK;
4499 }
4500
4501 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4502     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4503     IWineD3DStateBlockImpl *object = This->updateStateBlock;
4504
4505     if (!This->isRecordingState) {
4506         WARN("(%p) not recording! returning error\n", This);
4507         *ppStateBlock = NULL;
4508         return WINED3DERR_INVALIDCALL;
4509     }
4510
4511     stateblock_init_contained_states(object);
4512
4513     *ppStateBlock = (IWineD3DStateBlock*) object;
4514     This->isRecordingState = FALSE;
4515     This->updateStateBlock = This->stateBlock;
4516     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4517     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4518     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4519     return WINED3D_OK;
4520 }
4521
4522 /*****
4523  * Scene related functions
4524  *****/
4525 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4526     /* At the moment we have no need for any functionality at the beginning
4527        of a scene                                                          */
4528     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4529     TRACE("(%p)\n", This);
4530
4531     if(This->inScene) {
4532         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4533         return WINED3DERR_INVALIDCALL;
4534     }
4535     This->inScene = TRUE;
4536     return WINED3D_OK;
4537 }
4538
4539 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface)
4540 {
4541     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4542     struct wined3d_context *context;
4543
4544     TRACE("(%p)\n", This);
4545
4546     if(!This->inScene) {
4547         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4548         return WINED3DERR_INVALIDCALL;
4549     }
4550
4551     context = context_acquire(This, NULL);
4552     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4553     wglFlush();
4554     /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4555      * fails. */
4556     context_release(context);
4557
4558     This->inScene = FALSE;
4559     return WINED3D_OK;
4560 }
4561
4562 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4563         const RECT *pSourceRect, const RECT *pDestRect,
4564         HWND hDestWindowOverride, const RGNDATA *pDirtyRegion)
4565 {
4566     IWineD3DSwapChain *swapChain = NULL;
4567     int i;
4568     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4569
4570     TRACE("iface %p.\n", iface);
4571
4572     for(i = 0 ; i < swapchains ; i ++) {
4573
4574         IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain);
4575         TRACE("Presenting chain %d, %p.\n", i, swapChain);
4576         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4577         IWineD3DSwapChain_Release(swapChain);
4578     }
4579
4580     return WINED3D_OK;
4581 }
4582
4583 /* Do not call while under the GL lock. */
4584 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD rect_count,
4585         const RECT *rects, DWORD flags, WINED3DCOLOR color, float depth, DWORD stencil)
4586 {
4587     const WINED3DCOLORVALUE c = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)};
4588     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
4589     RECT draw_rect;
4590
4591     TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n",
4592             iface, rect_count, rects, flags, color, depth, stencil);
4593
4594     if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && !device->depth_stencil)
4595     {
4596         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4597         /* TODO: What about depth stencil buffers without stencil bits? */
4598         return WINED3DERR_INVALIDCALL;
4599     }
4600
4601     device_get_draw_rect(device, &draw_rect);
4602
4603     return device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
4604             device->render_targets, rect_count, rects, &draw_rect, flags, &c, depth, stencil);
4605 }
4606
4607 /*****
4608  * Drawing functions
4609  *****/
4610
4611 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
4612         WINED3DPRIMITIVETYPE primitive_type)
4613 {
4614     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615
4616     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
4617
4618     This->updateStateBlock->changed.primitive_type = TRUE;
4619     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
4620 }
4621
4622 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
4623         WINED3DPRIMITIVETYPE *primitive_type)
4624 {
4625     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626
4627     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
4628
4629     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
4630
4631     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
4632 }
4633
4634 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
4635 {
4636     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4637
4638     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
4639
4640     if(!This->stateBlock->vertexDecl) {
4641         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4642         return WINED3DERR_INVALIDCALL;
4643     }
4644
4645     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4646     if(This->stateBlock->streamIsUP) {
4647         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4648         This->stateBlock->streamIsUP = FALSE;
4649     }
4650
4651     if(This->stateBlock->loadBaseVertexIndex != 0) {
4652         This->stateBlock->loadBaseVertexIndex = 0;
4653         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4654     }
4655     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4656     drawPrimitive(iface, vertex_count, StartVertex /* start_idx */, 0 /* indxSize */, NULL /* indxData */);
4657     return WINED3D_OK;
4658 }
4659
4660 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, UINT startIndex, UINT index_count)
4661 {
4662     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4663     UINT                 idxStride = 2;
4664     IWineD3DBuffer *pIB;
4665     GLuint vbo;
4666
4667     pIB = This->stateBlock->pIndexData;
4668     if (!pIB) {
4669         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4670          * without an index buffer set. (The first time at least...)
4671          * D3D8 simply dies, but I doubt it can do much harm to return
4672          * D3DERR_INVALIDCALL there as well. */
4673         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4674         return WINED3DERR_INVALIDCALL;
4675     }
4676
4677     if(!This->stateBlock->vertexDecl) {
4678         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4679         return WINED3DERR_INVALIDCALL;
4680     }
4681
4682     if(This->stateBlock->streamIsUP) {
4683         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4684         This->stateBlock->streamIsUP = FALSE;
4685     }
4686     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
4687
4688     TRACE("(%p) : startIndex %u, index count %u.\n", This, startIndex, index_count);
4689
4690     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
4691         idxStride = 2;
4692     } else {
4693         idxStride = 4;
4694     }
4695
4696     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4697         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4698         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4699     }
4700
4701     drawPrimitive(iface, index_count, startIndex, idxStride,
4702             vbo ? NULL : ((struct wined3d_buffer *)pIB)->resource.allocatedMemory);
4703
4704     return WINED3D_OK;
4705 }
4706
4707 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
4708         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4709 {
4710     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4711     IWineD3DBuffer *vb;
4712
4713     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4714             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
4715
4716     if(!This->stateBlock->vertexDecl) {
4717         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4718         return WINED3DERR_INVALIDCALL;
4719     }
4720
4721     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4722     vb = This->stateBlock->streamSource[0];
4723     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4724     if (vb) IWineD3DBuffer_Release(vb);
4725     This->stateBlock->streamOffset[0] = 0;
4726     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4727     This->stateBlock->streamIsUP = TRUE;
4728     This->stateBlock->loadBaseVertexIndex = 0;
4729
4730     /* TODO: Only mark dirty if drawing from a different UP address */
4731     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4732
4733     drawPrimitive(iface, vertex_count, 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */);
4734
4735     /* MSDN specifies stream zero settings must be set to NULL */
4736     This->stateBlock->streamStride[0] = 0;
4737     This->stateBlock->streamSource[0] = NULL;
4738
4739     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4740      * the new stream sources or use UP drawing again
4741      */
4742     return WINED3D_OK;
4743 }
4744
4745 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
4746         UINT index_count, const void *pIndexData, enum wined3d_format_id IndexDataFormat,
4747         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4748 {
4749     int                 idxStride;
4750     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4751     IWineD3DBuffer *vb;
4752     IWineD3DBuffer *ib;
4753
4754     TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4755             This, index_count, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4756
4757     if(!This->stateBlock->vertexDecl) {
4758         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4759         return WINED3DERR_INVALIDCALL;
4760     }
4761
4762     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
4763         idxStride = 2;
4764     } else {
4765         idxStride = 4;
4766     }
4767
4768     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4769     vb = This->stateBlock->streamSource[0];
4770     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4771     if (vb) IWineD3DBuffer_Release(vb);
4772     This->stateBlock->streamIsUP = TRUE;
4773     This->stateBlock->streamOffset[0] = 0;
4774     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4775
4776     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4777     This->stateBlock->baseVertexIndex = 0;
4778     This->stateBlock->loadBaseVertexIndex = 0;
4779     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4780     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4781     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4782
4783     drawPrimitive(iface, index_count, 0 /* start_idx */, idxStride, pIndexData);
4784
4785     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4786     This->stateBlock->streamSource[0] = NULL;
4787     This->stateBlock->streamStride[0] = 0;
4788     ib = This->stateBlock->pIndexData;
4789     if(ib) {
4790         IWineD3DBuffer_Release(ib);
4791         This->stateBlock->pIndexData = NULL;
4792     }
4793     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4794      * SetStreamSource to specify a vertex buffer
4795      */
4796
4797     return WINED3D_OK;
4798 }
4799
4800 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
4801         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
4802 {
4803     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4804
4805     /* Mark the state dirty until we have nicer tracking
4806      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4807      * that value.
4808      */
4809     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4810     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4811     This->stateBlock->baseVertexIndex = 0;
4812     This->up_strided = DrawPrimStrideData;
4813     drawPrimitive(iface, vertex_count, 0, 0, NULL);
4814     This->up_strided = NULL;
4815     return WINED3D_OK;
4816 }
4817
4818 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
4819         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
4820         UINT NumVertices, const void *pIndexData, enum wined3d_format_id IndexDataFormat)
4821 {
4822     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4823     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
4824
4825     /* Mark the state dirty until we have nicer tracking
4826      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4827      * that value.
4828      */
4829     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4830     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4831     This->stateBlock->streamIsUP = TRUE;
4832     This->stateBlock->baseVertexIndex = 0;
4833     This->up_strided = DrawPrimStrideData;
4834     drawPrimitive(iface, vertex_count, 0 /* start_idx */, idxSize, pIndexData);
4835     This->up_strided = NULL;
4836     return WINED3D_OK;
4837 }
4838
4839 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
4840 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface,
4841         IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume)
4842 {
4843     WINED3DLOCKED_BOX src;
4844     WINED3DLOCKED_BOX dst;
4845     HRESULT hr;
4846
4847     TRACE("iface %p, src_volume %p, dst_volume %p.\n",
4848             iface, pSourceVolume, pDestinationVolume);
4849
4850     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
4851      * dirtification to improve loading performance.
4852      */
4853     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
4854     if(FAILED(hr)) return hr;
4855     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
4856     if(FAILED(hr)) {
4857     IWineD3DVolume_UnlockBox(pSourceVolume);
4858             return hr;
4859     }
4860
4861     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
4862
4863     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
4864     if(FAILED(hr)) {
4865         IWineD3DVolume_UnlockBox(pSourceVolume);
4866     } else {
4867         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
4868     }
4869     return hr;
4870 }
4871
4872 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice *iface,
4873         IWineD3DBaseTexture *src_texture, IWineD3DBaseTexture *dst_texture)
4874 {
4875     unsigned int level_count, i;
4876     WINED3DRESOURCETYPE type;
4877     HRESULT hr;
4878
4879     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
4880
4881     /* Verify that the source and destination textures are non-NULL. */
4882     if (!src_texture || !dst_texture)
4883     {
4884         WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
4885         return WINED3DERR_INVALIDCALL;
4886     }
4887
4888     if (src_texture == dst_texture)
4889     {
4890         WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
4891         return WINED3DERR_INVALIDCALL;
4892     }
4893
4894     /* Verify that the source and destination textures are the same type. */
4895     type = IWineD3DBaseTexture_GetType(src_texture);
4896     if (IWineD3DBaseTexture_GetType(dst_texture) != type)
4897     {
4898         WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
4899         return WINED3DERR_INVALIDCALL;
4900     }
4901
4902     /* Check that both textures have the identical numbers of levels. */
4903     level_count = IWineD3DBaseTexture_GetLevelCount(src_texture);
4904     if (IWineD3DBaseTexture_GetLevelCount(dst_texture) != level_count)
4905     {
4906         WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
4907         return WINED3DERR_INVALIDCALL;
4908     }
4909
4910     /* Make sure that the destination texture is loaded. */
4911     ((IWineD3DBaseTextureImpl *)dst_texture)->baseTexture.internal_preload(dst_texture, SRGB_RGB);
4912
4913     /* Update every surface level of the texture. */
4914     switch (type)
4915     {
4916         case WINED3DRTYPE_TEXTURE:
4917         {
4918             IWineD3DSurface *src_surface;
4919             IWineD3DSurface *dst_surface;
4920
4921             for (i = 0; i < level_count; ++i)
4922             {
4923                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)src_texture, i, &src_surface);
4924                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)dst_texture, i, &dst_surface);
4925                 hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4926                 IWineD3DSurface_Release(dst_surface);
4927                 IWineD3DSurface_Release(src_surface);
4928                 if (FAILED(hr))
4929                 {
4930                     WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4931                     return hr;
4932                 }
4933             }
4934             break;
4935         }
4936
4937         case WINED3DRTYPE_CUBETEXTURE:
4938         {
4939             IWineD3DSurface *src_surface;
4940             IWineD3DSurface *dst_surface;
4941             WINED3DCUBEMAP_FACES face;
4942
4943             for (i = 0; i < level_count; ++i)
4944             {
4945                 /* Update each cube face. */
4946                 for (face = WINED3DCUBEMAP_FACE_POSITIVE_X; face <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++face)
4947                 {
4948                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)src_texture,
4949                             face, i, &src_surface);
4950                     if (FAILED(hr)) ERR("Failed to get src cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4951                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)dst_texture,
4952                             face, i, &dst_surface);
4953                     if (FAILED(hr)) ERR("Failed to get dst cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4954                     hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4955                     IWineD3DSurface_Release(dst_surface);
4956                     IWineD3DSurface_Release(src_surface);
4957                     if (FAILED(hr))
4958                     {
4959                         WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4960                         return hr;
4961                     }
4962                 }
4963             }
4964             break;
4965         }
4966
4967         case WINED3DRTYPE_VOLUMETEXTURE:
4968         {
4969             IWineD3DVolume *src_volume;
4970             IWineD3DVolume *dst_volume;
4971
4972             for (i = 0; i < level_count; ++i)
4973             {
4974                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)src_texture, i, &src_volume);
4975                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)dst_texture, i, &dst_volume);
4976                 hr = IWineD3DDeviceImpl_UpdateVolume(iface, src_volume, dst_volume);
4977                 IWineD3DVolume_Release(dst_volume);
4978                 IWineD3DVolume_Release(src_volume);
4979                 if (FAILED(hr))
4980                 {
4981                     WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr);
4982                     return hr;
4983                 }
4984             }
4985             break;
4986         }
4987
4988         default:
4989             FIXME("Unsupported texture type %#x.\n", type);
4990             return WINED3DERR_INVALIDCALL;
4991     }
4992
4993     return WINED3D_OK;
4994 }
4995
4996 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,
4997         UINT swapchain_idx, IWineD3DSurface *dst_surface)
4998 {
4999     IWineD3DSwapChain *swapchain;
5000     HRESULT hr;
5001
5002     TRACE("iface %p, swapchain_idx %u, dst_surface %p.\n", iface, swapchain_idx, dst_surface);
5003
5004     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5005     if (FAILED(hr)) return hr;
5006
5007     hr = IWineD3DSwapChain_GetFrontBufferData(swapchain, dst_surface);
5008     IWineD3DSwapChain_Release(swapchain);
5009
5010     return hr;
5011 }
5012
5013 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5014     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5015     IWineD3DBaseTextureImpl *texture;
5016     DWORD i;
5017
5018     TRACE("(%p) : %p\n", This, pNumPasses);
5019
5020     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5021         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) {
5022             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5023             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5024         }
5025         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) {
5026             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5027             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5028         }
5029
5030         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5031         if (!texture || texture->resource.format->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5032
5033         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) {
5034             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5035             return E_FAIL;
5036         }
5037         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) {
5038             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5039             return E_FAIL;
5040         }
5041         if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE &&
5042            This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) {
5043             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5044             return E_FAIL;
5045         }
5046     }
5047
5048     /* return a sensible default */
5049     *pNumPasses = 1;
5050
5051     TRACE("returning D3D_OK\n");
5052     return WINED3D_OK;
5053 }
5054
5055 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5056 {
5057     int i;
5058
5059     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
5060     {
5061         IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5062         if (texture && (texture->resource.format->id == WINED3DFMT_P8_UINT
5063                 || texture->resource.format->id == WINED3DFMT_P8_UINT_A8_UNORM))
5064         {
5065             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5066         }
5067     }
5068 }
5069
5070 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5071     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5072     int j;
5073     UINT NewSize;
5074     PALETTEENTRY **palettes;
5075
5076     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5077
5078     if (PaletteNumber >= MAX_PALETTES) {
5079         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5080         return WINED3DERR_INVALIDCALL;
5081     }
5082
5083     if (PaletteNumber >= This->NumberOfPalettes) {
5084         NewSize = This->NumberOfPalettes;
5085         do {
5086            NewSize *= 2;
5087         } while(PaletteNumber >= NewSize);
5088         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5089         if (!palettes) {
5090             ERR("Out of memory!\n");
5091             return E_OUTOFMEMORY;
5092         }
5093         This->palettes = palettes;
5094         This->NumberOfPalettes = NewSize;
5095     }
5096
5097     if (!This->palettes[PaletteNumber]) {
5098         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5099         if (!This->palettes[PaletteNumber]) {
5100             ERR("Out of memory!\n");
5101             return E_OUTOFMEMORY;
5102         }
5103     }
5104
5105     for (j = 0; j < 256; ++j) {
5106         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5107         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5108         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5109         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5110     }
5111     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5112     TRACE("(%p) : returning\n", This);
5113     return WINED3D_OK;
5114 }
5115
5116 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5117     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5118     int j;
5119     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5120     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5121         /* What happens in such situation isn't documented; Native seems to silently abort
5122            on such conditions. Return Invalid Call. */
5123         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5124         return WINED3DERR_INVALIDCALL;
5125     }
5126     for (j = 0; j < 256; ++j) {
5127         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5128         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5129         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5130         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5131     }
5132     TRACE("(%p) : returning\n", This);
5133     return WINED3D_OK;
5134 }
5135
5136 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5137     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5138     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5139     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5140        (tested with reference rasterizer). Return Invalid Call. */
5141     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5142         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5143         return WINED3DERR_INVALIDCALL;
5144     }
5145     /*TODO: stateblocks */
5146     if (This->currentPalette != PaletteNumber) {
5147         This->currentPalette = PaletteNumber;
5148         dirtify_p8_texture_samplers(This);
5149     }
5150     TRACE("(%p) : returning\n", This);
5151     return WINED3D_OK;
5152 }
5153
5154 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5155     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5156     if (PaletteNumber == NULL) {
5157         WARN("(%p) : returning Invalid Call\n", This);
5158         return WINED3DERR_INVALIDCALL;
5159     }
5160     /*TODO: stateblocks */
5161     *PaletteNumber = This->currentPalette;
5162     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5163     return WINED3D_OK;
5164 }
5165
5166 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5167     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5168     static BOOL warned;
5169     if (!warned)
5170     {
5171         FIXME("(%p) : stub\n", This);
5172         warned = TRUE;
5173     }
5174
5175     This->softwareVertexProcessing = bSoftware;
5176     return WINED3D_OK;
5177 }
5178
5179
5180 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5181     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5182     static BOOL warned;
5183     if (!warned)
5184     {
5185         FIXME("(%p) : stub\n", This);
5186         warned = TRUE;
5187     }
5188     return This->softwareVertexProcessing;
5189 }
5190
5191 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface,
5192         UINT swapchain_idx, WINED3DRASTER_STATUS *raster_status)
5193 {
5194     IWineD3DSwapChain *swapchain;
5195     HRESULT hr;
5196
5197     TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
5198             iface, swapchain_idx, raster_status);
5199
5200     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5201     if (FAILED(hr))
5202     {
5203         WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx, hr);
5204         return hr;
5205     }
5206
5207     hr = IWineD3DSwapChain_GetRasterStatus(swapchain, raster_status);
5208     IWineD3DSwapChain_Release(swapchain);
5209     if (FAILED(hr))
5210     {
5211         WARN("Failed to get raster status, hr %#x.\n", hr);
5212         return hr;
5213     }
5214
5215     return WINED3D_OK;
5216 }
5217
5218 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments)
5219 {
5220     static BOOL warned;
5221     if(nSegments != 0.0f) {
5222         if (!warned)
5223         {
5224             FIXME("iface %p, nSegments %.8e stub!\n", iface, nSegments);
5225             warned = TRUE;
5226         }
5227     }
5228     return WINED3D_OK;
5229 }
5230
5231 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface)
5232 {
5233     static BOOL warned;
5234     if (!warned)
5235     {
5236         FIXME("iface %p stub!\n", iface);
5237         warned = TRUE;
5238     }
5239     return 0.0f;
5240 }
5241
5242 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
5243         IWineD3DSurface *src_surface, const RECT *src_rect,
5244         IWineD3DSurface *dst_surface, const POINT *dst_point)
5245 {
5246     IWineD3DSurfaceImpl *src_impl = (IWineD3DSurfaceImpl *)src_surface;
5247     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)dst_surface;
5248     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5249     const struct wined3d_format *src_format;
5250     const struct wined3d_format *dst_format;
5251     const struct wined3d_gl_info *gl_info;
5252     struct wined3d_context *context;
5253     const unsigned char *data;
5254     UINT update_w, update_h;
5255     CONVERT_TYPES convert;
5256     UINT src_w, src_h;
5257     UINT dst_x, dst_y;
5258     DWORD sampler;
5259     struct wined3d_format format;
5260
5261     TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
5262             iface, src_surface, wine_dbgstr_rect(src_rect),
5263             dst_surface, wine_dbgstr_point(dst_point));
5264
5265     if (src_impl->resource.pool != WINED3DPOOL_SYSTEMMEM || dst_impl->resource.pool != WINED3DPOOL_DEFAULT)
5266     {
5267         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
5268                 src_surface, dst_surface);
5269         return WINED3DERR_INVALIDCALL;
5270     }
5271
5272     src_format = src_impl->resource.format;
5273     dst_format = dst_impl->resource.format;
5274
5275     if (src_format->id != dst_format->id)
5276     {
5277         WARN("Source and destination surfaces should have the same format.\n");
5278         return WINED3DERR_INVALIDCALL;
5279     }
5280
5281     dst_x = dst_point ? dst_point->x : 0;
5282     dst_y = dst_point ? dst_point->y : 0;
5283
5284     /* This call loads the OpenGL surface directly, instead of copying the
5285      * surface to the destination's sysmem copy. If surface conversion is
5286      * needed, use BltFast instead to copy in sysmem and use regular surface
5287      * loading. */
5288     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &format, &convert);
5289     if (convert != NO_CONVERSION || format.convert)
5290         return IWineD3DSurface_BltFast(dst_surface, dst_x, dst_y, src_surface, src_rect, 0);
5291
5292     context = context_acquire(This, NULL);
5293     gl_info = context->gl_info;
5294
5295     ENTER_GL();
5296     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5297     checkGLcall("glActiveTextureARB");
5298     LEAVE_GL();
5299
5300     /* Make sure the surface is loaded and up to date */
5301     surface_internal_preload(dst_impl, SRGB_RGB);
5302     IWineD3DSurface_BindTexture(dst_surface, FALSE);
5303
5304     src_w = src_impl->currentDesc.Width;
5305     src_h = src_impl->currentDesc.Height;
5306     update_w = src_rect ? src_rect->right - src_rect->left : src_w;
5307     update_h = src_rect ? src_rect->bottom - src_rect->top : src_h;
5308
5309     data = IWineD3DSurface_GetData(src_surface);
5310     if (!data) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n");
5311
5312     ENTER_GL();
5313
5314     if (dst_format->Flags & WINED3DFMT_FLAG_COMPRESSED)
5315     {
5316         UINT row_length = wined3d_format_calculate_size(src_format, 1, update_w, 1);
5317         UINT row_count = (update_h + src_format->block_height - 1) / src_format->block_height;
5318         UINT src_pitch = wined3d_format_calculate_size(src_format, 1, src_w, 1);
5319
5320         if (src_rect)
5321         {
5322             data += (src_rect->top / src_format->block_height) * src_pitch;
5323             data += (src_rect->left / src_format->block_width) * src_format->block_byte_count;
5324         }
5325
5326         TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
5327                 "format %#x, image_size %#x, data %p.\n", dst_impl->texture_target, dst_impl->texture_level,
5328                 dst_x, dst_y, update_w, update_h, dst_format->glFormat, row_count * row_length, data);
5329
5330         if (row_length == src_pitch)
5331         {
5332             GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5333                     dst_x, dst_y, update_w, update_h, dst_format->glInternal, row_count * row_length, data));
5334         }
5335         else
5336         {
5337             UINT row, y;
5338
5339             /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
5340              * can't use the unpack row length like below. */
5341             for (row = 0, y = dst_y; row < row_count; ++row)
5342             {
5343                 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5344                         dst_x, y, update_w, src_format->block_height, dst_format->glInternal, row_length, data));
5345                 y += src_format->block_height;
5346                 data += src_pitch;
5347             }
5348         }
5349         checkGLcall("glCompressedTexSubImage2DARB");
5350     }
5351     else
5352     {
5353         if (src_rect)
5354         {
5355             data += src_rect->top * src_w * src_format->byte_count;
5356             data += src_rect->left * src_format->byte_count;
5357         }
5358
5359         TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n",
5360                 dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5361                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5362
5363         glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w);
5364         glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5365                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5366         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
5367         checkGLcall("glTexSubImage2D");
5368     }
5369
5370     LEAVE_GL();
5371     context_release(context);
5372
5373     surface_modify_location(dst_impl, SFLAG_INTEXTURE, TRUE);
5374     sampler = This->rev_tex_unit_map[0];
5375     if (sampler != WINED3D_UNMAPPED_STAGE)
5376     {
5377         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5378     }
5379
5380     return WINED3D_OK;
5381 }
5382
5383 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5384     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5385     struct WineD3DRectPatch *patch;
5386     GLenum old_primitive_type;
5387     unsigned int i;
5388     struct list *e;
5389     BOOL found;
5390     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5391
5392     if(!(Handle || pRectPatchInfo)) {
5393         /* TODO: Write a test for the return value, thus the FIXME */
5394         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5395         return WINED3DERR_INVALIDCALL;
5396     }
5397
5398     if(Handle) {
5399         i = PATCHMAP_HASHFUNC(Handle);
5400         found = FALSE;
5401         LIST_FOR_EACH(e, &This->patches[i]) {
5402             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5403             if(patch->Handle == Handle) {
5404                 found = TRUE;
5405                 break;
5406             }
5407         }
5408
5409         if(!found) {
5410             TRACE("Patch does not exist. Creating a new one\n");
5411             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5412             patch->Handle = Handle;
5413             list_add_head(&This->patches[i], &patch->entry);
5414         } else {
5415             TRACE("Found existing patch %p\n", patch);
5416         }
5417     } else {
5418         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5419          * attributes we have to tesselate, read back, and draw. This needs a patch
5420          * management structure instance. Create one.
5421          *
5422          * A possible improvement is to check if a vertex shader is used, and if not directly
5423          * draw the patch.
5424          */
5425         FIXME("Drawing an uncached patch. This is slow\n");
5426         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5427     }
5428
5429     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5430        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5431        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5432         HRESULT hr;
5433         TRACE("Tesselation density or patch info changed, retesselating\n");
5434
5435         if(pRectPatchInfo) {
5436             patch->RectPatchInfo = *pRectPatchInfo;
5437         }
5438         patch->numSegs[0] = pNumSegs[0];
5439         patch->numSegs[1] = pNumSegs[1];
5440         patch->numSegs[2] = pNumSegs[2];
5441         patch->numSegs[3] = pNumSegs[3];
5442
5443         hr = tesselate_rectpatch(This, patch);
5444         if(FAILED(hr)) {
5445             WARN("Patch tesselation failed\n");
5446
5447             /* Do not release the handle to store the params of the patch */
5448             if(!Handle) {
5449                 HeapFree(GetProcessHeap(), 0, patch);
5450             }
5451             return hr;
5452         }
5453     }
5454
5455     This->currentPatch = patch;
5456     old_primitive_type = This->stateBlock->gl_primitive_type;
5457     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5458     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5459     This->stateBlock->gl_primitive_type = old_primitive_type;
5460     This->currentPatch = NULL;
5461
5462     /* Destroy uncached patches */
5463     if(!Handle) {
5464         HeapFree(GetProcessHeap(), 0, patch->mem);
5465         HeapFree(GetProcessHeap(), 0, patch);
5466     }
5467     return WINED3D_OK;
5468 }
5469
5470 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface,
5471         UINT handle, const float *segment_count, const WINED3DTRIPATCH_INFO *patch_info)
5472 {
5473     FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5474             iface, handle, segment_count, patch_info);
5475
5476     return WINED3D_OK;
5477 }
5478
5479 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5480     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5481     int i;
5482     struct WineD3DRectPatch *patch;
5483     struct list *e;
5484     TRACE("(%p) Handle(%d)\n", This, Handle);
5485
5486     i = PATCHMAP_HASHFUNC(Handle);
5487     LIST_FOR_EACH(e, &This->patches[i]) {
5488         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5489         if(patch->Handle == Handle) {
5490             TRACE("Deleting patch %p\n", patch);
5491             list_remove(&patch->entry);
5492             HeapFree(GetProcessHeap(), 0, patch->mem);
5493             HeapFree(GetProcessHeap(), 0, patch);
5494             return WINED3D_OK;
5495         }
5496     }
5497
5498     /* TODO: Write a test for the return value */
5499     FIXME("Attempt to destroy nonexistent patch\n");
5500     return WINED3DERR_INVALIDCALL;
5501 }
5502
5503 /* Do not call while under the GL lock. */
5504 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface,
5505         IWineD3DSurface *surface, const RECT *rect, const WINED3DCOLORVALUE *color)
5506 {
5507     IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)surface;
5508
5509     TRACE("iface %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
5510             iface, surface, wine_dbgstr_rect(rect),
5511             color->r, color->g, color->b, color->a);
5512
5513     if (s->resource.pool != WINED3DPOOL_DEFAULT && s->resource.pool != WINED3DPOOL_SYSTEMMEM)
5514     {
5515         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5516         return WINED3DERR_INVALIDCALL;
5517     }
5518
5519     return surface_color_fill(s, rect, color);
5520 }
5521
5522 /* Do not call while under the GL lock. */
5523 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
5524         IWineD3DRendertargetView *rendertarget_view, const WINED3DCOLORVALUE *color)
5525 {
5526     IWineD3DResource *resource;
5527     HRESULT hr;
5528
5529     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
5530     if (FAILED(hr))
5531     {
5532         ERR("Failed to get resource, hr %#x\n", hr);
5533         return;
5534     }
5535
5536     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
5537     {
5538         FIXME("Only supported on surface resources\n");
5539         IWineD3DResource_Release(resource);
5540         return;
5541     }
5542
5543     hr = surface_color_fill((IWineD3DSurfaceImpl *)resource, NULL, color);
5544     if (FAILED(hr)) ERR("Color fill failed, hr %#x.\n", hr);
5545
5546     IWineD3DResource_Release(resource);
5547 }
5548
5549 /* rendertarget and depth stencil functions */
5550 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice *iface,
5551         DWORD render_target_idx, IWineD3DSurface **render_target)
5552 {
5553     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5554
5555     TRACE("iface %p, render_target_idx %u, render_target %p.\n",
5556             iface, render_target_idx, render_target);
5557
5558     if (render_target_idx >= device->adapter->gl_info.limits.buffers)
5559     {
5560         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
5561         return WINED3DERR_INVALIDCALL;
5562     }
5563
5564     *render_target = (IWineD3DSurface *)device->render_targets[render_target_idx];
5565     if (*render_target) IWineD3DSurface_AddRef(*render_target);
5566
5567     TRACE("Returning render target %p.\n", *render_target);
5568
5569     return WINED3D_OK;
5570 }
5571
5572 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface,
5573         IWineD3DSurface *front, IWineD3DSurface *back)
5574 {
5575     IWineD3DSurfaceImpl *front_impl = (IWineD3DSurfaceImpl *)front;
5576     IWineD3DSurfaceImpl *back_impl = (IWineD3DSurfaceImpl *)back;
5577     IWineD3DSwapChainImpl *swapchain;
5578     HRESULT hr;
5579
5580     TRACE("iface %p, front %p, back %p.\n", iface, front, back);
5581
5582     if (FAILED(hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&swapchain)))
5583     {
5584         ERR("Failed to get the swapchain, hr %#x.\n", hr);
5585         return hr;
5586     }
5587
5588     if (front_impl && !(front_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5589     {
5590         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5591         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5592         return WINED3DERR_INVALIDCALL;
5593     }
5594
5595     if (back_impl)
5596     {
5597         if (!(back_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5598         {
5599             ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5600             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5601             return WINED3DERR_INVALIDCALL;
5602         }
5603
5604         if (!swapchain->back_buffers)
5605         {
5606             swapchain->back_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*swapchain->back_buffers));
5607             if (!swapchain->back_buffers)
5608             {
5609                 ERR("Failed to allocate back buffer array memory.\n");
5610                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5611                 return E_OUTOFMEMORY;
5612             }
5613         }
5614     }
5615
5616     if (swapchain->front_buffer != front_impl)
5617     {
5618         TRACE("Changing the front buffer from %p to %p.\n", swapchain->front_buffer, front_impl);
5619
5620         if (swapchain->front_buffer)
5621             surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_NONE, NULL);
5622         swapchain->front_buffer = front_impl;
5623
5624         if (front_impl)
5625             surface_set_container(front_impl, WINED3D_CONTAINER_SWAPCHAIN, (IWineD3DBase *)swapchain);
5626     }
5627
5628     if (swapchain->back_buffers[0] != back_impl)
5629     {
5630         TRACE("Changing the back buffer from %p to %p.\n", swapchain->back_buffers[0], back_impl);
5631
5632         if (swapchain->back_buffers[0])
5633             surface_set_container(swapchain->back_buffers[0], WINED3D_CONTAINER_NONE, NULL);
5634         swapchain->back_buffers[0] = back_impl;
5635
5636         if (back_impl)
5637         {
5638             swapchain->presentParms.BackBufferWidth = back_impl->currentDesc.Width;
5639             swapchain->presentParms.BackBufferHeight = back_impl->currentDesc.Height;
5640             swapchain->presentParms.BackBufferFormat = back_impl->resource.format->id;
5641             swapchain->presentParms.BackBufferCount = 1;
5642
5643             surface_set_container(back_impl, WINED3D_CONTAINER_SWAPCHAIN, (IWineD3DBase *)swapchain);
5644         }
5645         else
5646         {
5647             swapchain->presentParms.BackBufferCount = 0;
5648             HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
5649             swapchain->back_buffers = NULL;
5650         }
5651     }
5652
5653     IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5654     return WINED3D_OK;
5655 }
5656
5657 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface **depth_stencil)
5658 {
5659     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5660
5661     TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
5662
5663     *depth_stencil = (IWineD3DSurface *)device->depth_stencil;
5664     TRACE("Returning depth/stencil surface %p.\n", *depth_stencil);
5665     if (!*depth_stencil) return WINED3DERR_NOTFOUND;
5666     IWineD3DSurface_AddRef(*depth_stencil);
5667
5668     return WINED3D_OK;
5669 }
5670
5671 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
5672         DWORD render_target_idx, IWineD3DSurface *render_target, BOOL set_viewport)
5673 {
5674     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5675     IWineD3DSurfaceImpl *prev;
5676
5677     TRACE("iface %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
5678             iface, render_target_idx, render_target, set_viewport);
5679
5680     if (render_target_idx >= device->adapter->gl_info.limits.buffers)
5681     {
5682         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
5683         return WINED3DERR_INVALIDCALL;
5684     }
5685
5686     prev = device->render_targets[render_target_idx];
5687     if (render_target == (IWineD3DSurface *)prev)
5688     {
5689         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5690         return WINED3D_OK;
5691     }
5692
5693     /* Render target 0 can't be set to NULL. */
5694     if (!render_target && !render_target_idx)
5695     {
5696         WARN("Trying to set render target 0 to NULL.\n");
5697         return WINED3DERR_INVALIDCALL;
5698     }
5699
5700     if (render_target && !(((IWineD3DSurfaceImpl *)render_target)->resource.usage & WINED3DUSAGE_RENDERTARGET))
5701     {
5702         FIXME("Surface %p doesn't have render target usage.\n", render_target);
5703         return WINED3DERR_INVALIDCALL;
5704     }
5705
5706     if (render_target) IWineD3DSurface_AddRef(render_target);
5707     device->render_targets[render_target_idx] = (IWineD3DSurfaceImpl *)render_target;
5708     /* Release after the assignment, to prevent device_resource_released()
5709      * from seeing the surface as still in use. */
5710     if (prev) IWineD3DSurface_Release((IWineD3DSurface *)prev);
5711
5712     /* Render target 0 is special. */
5713     if (!render_target_idx && set_viewport)
5714     {
5715         /* Set the viewport and scissor rectangles, if requested. Tests show
5716          * that stateblock recording is ignored, the change goes directly
5717          * into the primary stateblock. */
5718         device->stateBlock->viewport.Height = device->render_targets[0]->currentDesc.Height;
5719         device->stateBlock->viewport.Width  = device->render_targets[0]->currentDesc.Width;
5720         device->stateBlock->viewport.X      = 0;
5721         device->stateBlock->viewport.Y      = 0;
5722         device->stateBlock->viewport.MaxZ   = 1.0f;
5723         device->stateBlock->viewport.MinZ   = 0.0f;
5724         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_VIEWPORT);
5725
5726         device->stateBlock->scissorRect.top = 0;
5727         device->stateBlock->scissorRect.left = 0;
5728         device->stateBlock->scissorRect.right = device->stateBlock->viewport.Width;
5729         device->stateBlock->scissorRect.bottom = device->stateBlock->viewport.Height;
5730         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SCISSORRECT);
5731     }
5732
5733     return WINED3D_OK;
5734 }
5735
5736 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil)
5737 {
5738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5739     IWineD3DSurfaceImpl *tmp;
5740
5741     TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This, depth_stencil, This->depth_stencil);
5742
5743     if (This->depth_stencil == (IWineD3DSurfaceImpl *)depth_stencil)
5744     {
5745         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5746         return WINED3D_OK;
5747     }
5748
5749     if (This->depth_stencil)
5750     {
5751         if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5752                 || This->depth_stencil->Flags & SFLAG_DISCARD)
5753         {
5754             surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED,
5755                     This->depth_stencil->currentDesc.Width,
5756                     This->depth_stencil->currentDesc.Height);
5757             if (This->depth_stencil == This->onscreen_depth_stencil)
5758             {
5759                 IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
5760                 This->onscreen_depth_stencil = NULL;
5761             }
5762         }
5763     }
5764
5765     tmp = This->depth_stencil;
5766     This->depth_stencil = (IWineD3DSurfaceImpl *)depth_stencil;
5767     if (This->depth_stencil) IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil);
5768     if (tmp) IWineD3DSurface_Release((IWineD3DSurface *)tmp);
5769
5770     if ((!tmp && depth_stencil) || (!depth_stencil && tmp))
5771     {
5772         /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5773         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5774         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5775         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5776     }
5777
5778     return WINED3D_OK;
5779 }
5780
5781 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice *iface,
5782         UINT XHotSpot, UINT YHotSpot, IWineD3DSurface *cursor_image)
5783 {
5784     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5785     IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)cursor_image;
5786     WINED3DLOCKED_RECT lockedRect;
5787
5788     TRACE("iface %p, hotspot_x %u, hotspot_y %u, cursor_image %p.\n",
5789             iface, XHotSpot, YHotSpot, cursor_image);
5790
5791     /* some basic validation checks */
5792     if (This->cursorTexture)
5793     {
5794         struct wined3d_context *context = context_acquire(This, NULL);
5795         ENTER_GL();
5796         glDeleteTextures(1, &This->cursorTexture);
5797         LEAVE_GL();
5798         context_release(context);
5799         This->cursorTexture = 0;
5800     }
5801
5802     if ((s->currentDesc.Width == 32) && (s->currentDesc.Height == 32))
5803         This->haveHardwareCursor = TRUE;
5804     else
5805         This->haveHardwareCursor = FALSE;
5806
5807     if (cursor_image)
5808     {
5809         WINED3DLOCKED_RECT rect;
5810
5811         /* MSDN: Cursor must be A8R8G8B8 */
5812         if (s->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM)
5813         {
5814             WARN("surface %p has an invalid format.\n", cursor_image);
5815             return WINED3DERR_INVALIDCALL;
5816         }
5817
5818         /* MSDN: Cursor must be smaller than the display mode */
5819         if (s->currentDesc.Width > This->ddraw_width
5820                 || s->currentDesc.Height > This->ddraw_height)
5821         {
5822             WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
5823                     s, s->currentDesc.Width, s->currentDesc.Height, This->ddraw_width, This->ddraw_height);
5824             return WINED3DERR_INVALIDCALL;
5825         }
5826
5827         if (!This->haveHardwareCursor) {
5828             /* TODO: MSDN: Cursor sizes must be a power of 2 */
5829
5830             /* Do not store the surface's pointer because the application may
5831              * release it after setting the cursor image. Windows doesn't
5832              * addref the set surface, so we can't do this either without
5833              * creating circular refcount dependencies. Copy out the gl texture
5834              * instead.
5835              */
5836             This->cursorWidth = s->currentDesc.Width;
5837             This->cursorHeight = s->currentDesc.Height;
5838             if (SUCCEEDED(IWineD3DSurface_LockRect(cursor_image, &rect, NULL, WINED3DLOCK_READONLY)))
5839             {
5840                 const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
5841                 const struct wined3d_format *format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
5842                 struct wined3d_context *context;
5843                 char *mem, *bits = rect.pBits;
5844                 GLint intfmt = format->glInternal;
5845                 GLint gl_format = format->glFormat;
5846                 GLint type = format->glType;
5847                 INT height = This->cursorHeight;
5848                 INT width = This->cursorWidth;
5849                 INT bpp = format->byte_count;
5850                 DWORD sampler;
5851                 INT i;
5852
5853                 /* Reformat the texture memory (pitch and width can be
5854                  * different) */
5855                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
5856                 for(i = 0; i < height; i++)
5857                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
5858                 IWineD3DSurface_UnlockRect(cursor_image);
5859
5860                 context = context_acquire(This, NULL);
5861
5862                 ENTER_GL();
5863
5864                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
5865                 {
5866                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
5867                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5868                 }
5869
5870                 /* Make sure that a proper texture unit is selected */
5871                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5872                 checkGLcall("glActiveTextureARB");
5873                 sampler = This->rev_tex_unit_map[0];
5874                 if (sampler != WINED3D_UNMAPPED_STAGE)
5875                 {
5876                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5877                 }
5878                 /* Create a new cursor texture */
5879                 glGenTextures(1, &This->cursorTexture);
5880                 checkGLcall("glGenTextures");
5881                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
5882                 checkGLcall("glBindTexture");
5883                 /* Copy the bitmap memory into the cursor texture */
5884                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, gl_format, type, mem);
5885                 HeapFree(GetProcessHeap(), 0, mem);
5886                 checkGLcall("glTexImage2D");
5887
5888                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
5889                 {
5890                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
5891                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
5892                 }
5893
5894                 LEAVE_GL();
5895
5896                 context_release(context);
5897             }
5898             else
5899             {
5900                 FIXME("A cursor texture was not returned.\n");
5901                 This->cursorTexture = 0;
5902             }
5903         }
5904         else
5905         {
5906             /* Draw a hardware cursor */
5907             ICONINFO cursorInfo;
5908             HCURSOR cursor;
5909             /* Create and clear maskBits because it is not needed for
5910              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
5911              * chunks. */
5912             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5913                     (s->currentDesc.Width * s->currentDesc.Height / 8));
5914             IWineD3DSurface_LockRect(cursor_image, &lockedRect, NULL,
5915                     WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY);
5916             TRACE("width: %u height: %u.\n", s->currentDesc.Width, s->currentDesc.Height);
5917
5918             cursorInfo.fIcon = FALSE;
5919             cursorInfo.xHotspot = XHotSpot;
5920             cursorInfo.yHotspot = YHotSpot;
5921             cursorInfo.hbmMask = CreateBitmap(s->currentDesc.Width, s->currentDesc.Height, 1, 1, maskBits);
5922             cursorInfo.hbmColor = CreateBitmap(s->currentDesc.Width, s->currentDesc.Height, 1, 32, lockedRect.pBits);
5923             IWineD3DSurface_UnlockRect(cursor_image);
5924             /* Create our cursor and clean up. */
5925             cursor = CreateIconIndirect(&cursorInfo);
5926             SetCursor(cursor);
5927             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
5928             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
5929             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
5930             This->hardwareCursor = cursor;
5931             HeapFree(GetProcessHeap(), 0, maskBits);
5932         }
5933     }
5934
5935     This->xHotSpot = XHotSpot;
5936     This->yHotSpot = YHotSpot;
5937     return WINED3D_OK;
5938 }
5939
5940 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5941     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5942     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5943
5944     This->xScreenSpace = XScreenSpace;
5945     This->yScreenSpace = YScreenSpace;
5946
5947     return;
5948
5949 }
5950
5951 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5952     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5953     BOOL oldVisible = This->bCursorVisible;
5954     POINT pt;
5955
5956     TRACE("(%p) : visible(%d)\n", This, bShow);
5957
5958     /*
5959      * When ShowCursor is first called it should make the cursor appear at the OS's last
5960      * known cursor position.  Because of this, some applications just repetitively call
5961      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5962      */
5963     GetCursorPos(&pt);
5964     This->xScreenSpace = pt.x;
5965     This->yScreenSpace = pt.y;
5966
5967     if (This->haveHardwareCursor) {
5968         This->bCursorVisible = bShow;
5969         if (bShow)
5970             SetCursor(This->hardwareCursor);
5971         else
5972             SetCursor(NULL);
5973     }
5974     else
5975     {
5976         if (This->cursorTexture)
5977             This->bCursorVisible = bShow;
5978     }
5979
5980     return oldVisible;
5981 }
5982
5983 static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) {
5984     TRACE("checking resource %p for eviction\n", resource);
5985     if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) {
5986         TRACE("Evicting %p\n", resource);
5987         IWineD3DResource_UnLoad(resource);
5988     }
5989     IWineD3DResource_Release(resource);
5990     return S_OK;
5991 }
5992
5993 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice *iface)
5994 {
5995     TRACE("iface %p.\n", iface);
5996
5997     IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL);
5998     /* Invalidate stream sources, the buffer(s) may have been evicted. */
5999     IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)iface, STATE_STREAMSRC);
6000
6001     return WINED3D_OK;
6002 }
6003
6004 static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
6005 {
6006     IWineD3DDeviceImpl *device = surface->resource.device;
6007     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6008
6009     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6010     if(surface->Flags & SFLAG_DIBSECTION) {
6011         /* Release the DC */
6012         SelectObject(surface->hDC, surface->dib.holdbitmap);
6013         DeleteDC(surface->hDC);
6014         /* Release the DIB section */
6015         DeleteObject(surface->dib.DIBsection);
6016         surface->dib.bitmap_data = NULL;
6017         surface->resource.allocatedMemory = NULL;
6018         surface->Flags &= ~SFLAG_DIBSECTION;
6019     }
6020     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6021     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6022     if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
6023             || gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
6024     {
6025         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6026         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6027     } else {
6028         surface->pow2Width = surface->pow2Height = 1;
6029         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6030         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6031     }
6032
6033     if (surface->texture_name)
6034     {
6035         struct wined3d_context *context = context_acquire(device, NULL);
6036         ENTER_GL();
6037         glDeleteTextures(1, &surface->texture_name);
6038         LEAVE_GL();
6039         context_release(context);
6040         surface->texture_name = 0;
6041         surface->Flags &= ~SFLAG_CLIENT;
6042     }
6043     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6044        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6045         surface->Flags |= SFLAG_NONPOW2;
6046     } else  {
6047         surface->Flags &= ~SFLAG_NONPOW2;
6048     }
6049     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
6050     surface->resource.allocatedMemory = NULL;
6051     surface->resource.heapMemory = NULL;
6052     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6053
6054     /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6055      * to a FBO */
6056     if (!surface_init_sysmem(surface))
6057     {
6058         return E_OUTOFMEMORY;
6059     }
6060     return WINED3D_OK;
6061 }
6062
6063 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6064     TRACE("Unloading resource %p\n", resource);
6065     IWineD3DResource_UnLoad(resource);
6066     IWineD3DResource_Release(resource);
6067     return S_OK;
6068 }
6069
6070 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
6071 {
6072     UINT i, count;
6073     WINED3DDISPLAYMODE m;
6074     HRESULT hr;
6075
6076     /* All Windowed modes are supported, as is leaving the current mode */
6077     if(pp->Windowed) return TRUE;
6078     if(!pp->BackBufferWidth) return TRUE;
6079     if(!pp->BackBufferHeight) return TRUE;
6080
6081     count = IWineD3D_GetAdapterModeCount(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN);
6082     for(i = 0; i < count; i++) {
6083         memset(&m, 0, sizeof(m));
6084         hr = IWineD3D_EnumAdapterModes(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN, i, &m);
6085         if(FAILED(hr)) {
6086             ERR("EnumAdapterModes failed\n");
6087         }
6088         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
6089             /* Mode found, it is supported */
6090             return TRUE;
6091         }
6092     }
6093     /* Mode not found -> not supported */
6094     return FALSE;
6095 }
6096
6097 /* Do not call while under the GL lock. */
6098 static void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6099 {
6100     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6101     const struct wined3d_gl_info *gl_info;
6102     struct wined3d_context *context;
6103     IWineD3DBaseShaderImpl *shader;
6104
6105     context = context_acquire(This, NULL);
6106     gl_info = context->gl_info;
6107
6108     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6109     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6110         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6111     }
6112
6113     ENTER_GL();
6114     if(This->depth_blt_texture) {
6115         glDeleteTextures(1, &This->depth_blt_texture);
6116         This->depth_blt_texture = 0;
6117     }
6118     if (This->depth_blt_rb) {
6119         gl_info->fbo_ops.glDeleteRenderbuffers(1, &This->depth_blt_rb);
6120         This->depth_blt_rb = 0;
6121         This->depth_blt_rb_w = 0;
6122         This->depth_blt_rb_h = 0;
6123     }
6124     LEAVE_GL();
6125
6126     This->blitter->free_private(iface);
6127     This->frag_pipe->free_private(iface);
6128     This->shader_backend->shader_free_private(iface);
6129     destroy_dummy_textures(This, gl_info);
6130
6131     context_release(context);
6132
6133     while (This->numContexts)
6134     {
6135         context_destroy(This, This->contexts[0]);
6136     }
6137     HeapFree(GetProcessHeap(), 0, swapchain->context);
6138     swapchain->context = NULL;
6139     swapchain->num_contexts = 0;
6140 }
6141
6142 /* Do not call while under the GL lock. */
6143 static HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6144 {
6145     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6146     struct wined3d_context *context;
6147     HRESULT hr;
6148     IWineD3DSurfaceImpl *target;
6149
6150     /* Recreate the primary swapchain's context */
6151     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
6152     if (!swapchain->context)
6153     {
6154         ERR("Failed to allocate memory for swapchain context array.\n");
6155         return E_OUTOFMEMORY;
6156     }
6157
6158     target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
6159     if (!(context = context_create(swapchain, target, swapchain->ds_format)))
6160     {
6161         WARN("Failed to create context.\n");
6162         HeapFree(GetProcessHeap(), 0, swapchain->context);
6163         return E_FAIL;
6164     }
6165
6166     swapchain->context[0] = context;
6167     swapchain->num_contexts = 1;
6168     create_dummy_textures(This);
6169     context_release(context);
6170
6171     hr = This->shader_backend->shader_alloc_private(iface);
6172     if (FAILED(hr))
6173     {
6174         ERR("Failed to allocate shader private data, hr %#x.\n", hr);
6175         goto err;
6176     }
6177
6178     hr = This->frag_pipe->alloc_private(iface);
6179     if (FAILED(hr))
6180     {
6181         ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr);
6182         This->shader_backend->shader_free_private(iface);
6183         goto err;
6184     }
6185
6186     hr = This->blitter->alloc_private(iface);
6187     if (FAILED(hr))
6188     {
6189         ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
6190         This->frag_pipe->free_private(iface);
6191         This->shader_backend->shader_free_private(iface);
6192         goto err;
6193     }
6194
6195     return WINED3D_OK;
6196
6197 err:
6198     context_acquire(This, NULL);
6199     destroy_dummy_textures(This, context->gl_info);
6200     context_release(context);
6201     context_destroy(This, context);
6202     HeapFree(GetProcessHeap(), 0, swapchain->context);
6203     swapchain->num_contexts = 0;
6204     return hr;
6205 }
6206
6207 /* Do not call while under the GL lock. */
6208 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice *iface,
6209         WINED3DPRESENT_PARAMETERS *pPresentationParameters)
6210 {
6211     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6212     IWineD3DSwapChainImpl *swapchain;
6213     HRESULT hr;
6214     BOOL DisplayModeChanged = FALSE;
6215     WINED3DDISPLAYMODE mode;
6216     TRACE("(%p)\n", This);
6217
6218     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6219     if(FAILED(hr)) {
6220         ERR("Failed to get the first implicit swapchain\n");
6221         return hr;
6222     }
6223
6224     if(!is_display_mode_supported(This, pPresentationParameters)) {
6225         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6226         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
6227              pPresentationParameters->BackBufferHeight);
6228         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6229         return WINED3DERR_INVALIDCALL;
6230     }
6231
6232     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6233      * on an existing gl context, so there's no real need for recreation.
6234      *
6235      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6236      *
6237      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6238      */
6239     TRACE("New params:\n");
6240     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6241     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6242     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6243     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6244     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6245     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6246     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6247     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6248     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6249     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6250     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6251     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6252     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6253
6254     /* No special treatment of these parameters. Just store them */
6255     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6256     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6257     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6258     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6259
6260     /* What to do about these? */
6261     if(pPresentationParameters->BackBufferCount != 0 &&
6262         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6263         ERR("Cannot change the back buffer count yet\n");
6264     }
6265     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6266         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6267         ERR("Cannot change the back buffer format yet\n");
6268     }
6269     if(pPresentationParameters->hDeviceWindow != NULL &&
6270         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6271         ERR("Cannot change the device window yet\n");
6272     }
6273     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil)
6274     {
6275         HRESULT hrc;
6276
6277         TRACE("Creating the depth stencil buffer\n");
6278
6279         hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
6280                 pPresentationParameters->BackBufferWidth,
6281                 pPresentationParameters->BackBufferHeight,
6282                 pPresentationParameters->AutoDepthStencilFormat,
6283                 pPresentationParameters->MultiSampleType,
6284                 pPresentationParameters->MultiSampleQuality,
6285                 FALSE,
6286                 (IWineD3DSurface **)&This->auto_depth_stencil);
6287
6288         if (FAILED(hrc)) {
6289             ERR("Failed to create the depth stencil buffer\n");
6290             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6291             return WINED3DERR_INVALIDCALL;
6292         }
6293     }
6294
6295     if (This->onscreen_depth_stencil)
6296     {
6297         IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
6298         This->onscreen_depth_stencil = NULL;
6299     }
6300
6301     /* Reset the depth stencil */
6302     if (pPresentationParameters->EnableAutoDepthStencil)
6303         IWineD3DDevice_SetDepthStencilSurface(iface, (IWineD3DSurface *)This->auto_depth_stencil);
6304     else
6305         IWineD3DDevice_SetDepthStencilSurface(iface, NULL);
6306
6307     TRACE("Resetting stateblock\n");
6308     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
6309     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
6310
6311     delete_opengl_contexts(iface, swapchain);
6312
6313     if(pPresentationParameters->Windowed) {
6314         mode.Width = swapchain->orig_width;
6315         mode.Height = swapchain->orig_height;
6316         mode.RefreshRate = 0;
6317         mode.Format = swapchain->presentParms.BackBufferFormat;
6318     } else {
6319         mode.Width = pPresentationParameters->BackBufferWidth;
6320         mode.Height = pPresentationParameters->BackBufferHeight;
6321         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6322         mode.Format = swapchain->presentParms.BackBufferFormat;
6323     }
6324
6325     /* Should Width == 800 && Height == 0 set 800x600? */
6326     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6327        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6328         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6329     {
6330         UINT i;
6331
6332         if(!pPresentationParameters->Windowed) {
6333             DisplayModeChanged = TRUE;
6334         }
6335         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6336         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6337
6338         hr = updateSurfaceDesc(swapchain->front_buffer, pPresentationParameters);
6339         if(FAILED(hr))
6340         {
6341             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6342             return hr;
6343         }
6344
6345         for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i)
6346         {
6347             hr = updateSurfaceDesc(swapchain->back_buffers[i], pPresentationParameters);
6348             if(FAILED(hr))
6349             {
6350                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6351                 return hr;
6352             }
6353         }
6354         if (This->auto_depth_stencil)
6355         {
6356             hr = updateSurfaceDesc(This->auto_depth_stencil, pPresentationParameters);
6357             if(FAILED(hr))
6358             {
6359                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6360                 return hr;
6361             }
6362         }
6363     }
6364
6365     if (!pPresentationParameters->Windowed != !swapchain->presentParms.Windowed
6366             || DisplayModeChanged)
6367     {
6368         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6369
6370         if (!pPresentationParameters->Windowed)
6371         {
6372             if(swapchain->presentParms.Windowed) {
6373                 /* switch from windowed to fs */
6374                 swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6375                         pPresentationParameters->BackBufferHeight);
6376             } else {
6377                 /* Fullscreen -> fullscreen mode change */
6378                 MoveWindow(swapchain->device_window, 0, 0,
6379                            pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
6380                            TRUE);
6381             }
6382         }
6383         else if (!swapchain->presentParms.Windowed)
6384         {
6385             /* Fullscreen -> windowed switch */
6386             swapchain_restore_fullscreen_window(swapchain);
6387         }
6388         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6389     } else if(!pPresentationParameters->Windowed) {
6390         DWORD style = This->style, exStyle = This->exStyle;
6391         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6392          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6393          * Reset to clear up their mess. Guild Wars also loses the device during that.
6394          */
6395         This->style = 0;
6396         This->exStyle = 0;
6397         swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6398                 pPresentationParameters->BackBufferHeight);
6399         This->style = style;
6400         This->exStyle = exStyle;
6401     }
6402
6403     /* Note: No parent needed for initial internal stateblock */
6404     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock);
6405     if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6406     else TRACE("Created stateblock %p\n", This->stateBlock);
6407     This->updateStateBlock = This->stateBlock;
6408     IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
6409
6410     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
6411     if(FAILED(hr)) {
6412         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6413     }
6414
6415     if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
6416     {
6417         RECT client_rect;
6418         GetClientRect(swapchain->win_handle, &client_rect);
6419
6420         if(!swapchain->presentParms.BackBufferCount)
6421         {
6422             TRACE("Single buffered rendering\n");
6423             swapchain->render_to_fbo = FALSE;
6424         }
6425         else if(swapchain->presentParms.BackBufferWidth  != client_rect.right  ||
6426                 swapchain->presentParms.BackBufferHeight != client_rect.bottom )
6427         {
6428             TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6429                     swapchain->presentParms.BackBufferWidth,
6430                     swapchain->presentParms.BackBufferHeight,
6431                     client_rect.right, client_rect.bottom);
6432             swapchain->render_to_fbo = TRUE;
6433         }
6434         else
6435         {
6436             TRACE("Rendering directly to GL_BACK\n");
6437             swapchain->render_to_fbo = FALSE;
6438         }
6439     }
6440
6441     hr = create_primary_opengl_context(iface, swapchain);
6442     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6443
6444     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6445      * first use
6446      */
6447     return hr;
6448 }
6449
6450 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL enable_dialogs)
6451 {
6452     TRACE("iface %p, enable_dialogs %#x.\n", iface, enable_dialogs);
6453
6454     if (!enable_dialogs) FIXME("Dialogs cannot be disabled yet.\n");
6455
6456     return WINED3D_OK;
6457 }
6458
6459
6460 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6461     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6462     TRACE("(%p) : pParameters %p\n", This, pParameters);
6463
6464     *pParameters = This->createParms;
6465     return WINED3D_OK;
6466 }
6467
6468 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6469     IWineD3DSwapChain *swapchain;
6470
6471     TRACE("Relaying  to swapchain\n");
6472
6473     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6474         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, pRamp);
6475         IWineD3DSwapChain_Release(swapchain);
6476     }
6477 }
6478
6479 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6480     IWineD3DSwapChain *swapchain;
6481
6482     TRACE("Relaying  to swapchain\n");
6483
6484     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6485         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6486         IWineD3DSwapChain_Release(swapchain);
6487     }
6488 }
6489
6490
6491 /** ********************************************************
6492 *   Notification functions
6493 ** ********************************************************/
6494 /** This function must be called in the release of a resource when ref == 0,
6495 * the contents of resource must still be correct,
6496 * any handles to other resource held by the caller must be closed
6497 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6498  *****************************************************/
6499 void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6500 {
6501     TRACE("(%p) : Adding resource %p\n", This, resource);
6502
6503     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6504 }
6505
6506 static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6507 {
6508     TRACE("(%p) : Removing resource %p\n", This, resource);
6509
6510     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6511 }
6512
6513 void device_resource_released(IWineD3DDeviceImpl *device, IWineD3DResource *resource)
6514 {
6515     WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource);
6516     unsigned int i;
6517
6518     TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type));
6519
6520     context_resource_released(device, resource, type);
6521
6522     switch (type)
6523     {
6524         case WINED3DRTYPE_SURFACE:
6525             if (!device->d3d_initialized) break;
6526
6527             for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
6528             {
6529                 if (device->render_targets[i] == (IWineD3DSurfaceImpl *)resource)
6530                 {
6531                     ERR("Surface %p is still in use as render target %u.\n", resource, i);
6532                     device->render_targets[i] = NULL;
6533                 }
6534             }
6535
6536             if (device->depth_stencil == (IWineD3DSurfaceImpl *)resource)
6537             {
6538                 ERR("Surface %p is still in use as depth/stencil buffer.\n", resource);
6539                 device->depth_stencil = NULL;
6540             }
6541             break;
6542
6543         case WINED3DRTYPE_TEXTURE:
6544         case WINED3DRTYPE_CUBETEXTURE:
6545         case WINED3DRTYPE_VOLUMETEXTURE:
6546             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
6547             {
6548                 if (device->stateBlock && device->stateBlock->textures[i] == (IWineD3DBaseTexture *)resource)
6549                 {
6550                     ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6551                             resource, device->stateBlock, i);
6552                     device->stateBlock->textures[i] = NULL;
6553                 }
6554
6555                 if (device->updateStateBlock != device->stateBlock
6556                         && device->updateStateBlock->textures[i] == (IWineD3DBaseTexture *)resource)
6557                 {
6558                     ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6559                             resource, device->updateStateBlock, i);
6560                     device->updateStateBlock->textures[i] = NULL;
6561                 }
6562             }
6563             break;
6564
6565         case WINED3DRTYPE_BUFFER:
6566             for (i = 0; i < MAX_STREAMS; ++i)
6567             {
6568                 if (device->stateBlock && device->stateBlock->streamSource[i] == (IWineD3DBuffer *)resource)
6569                 {
6570                     ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6571                             resource, device->stateBlock, i);
6572                     device->stateBlock->streamSource[i] = NULL;
6573                 }
6574
6575                 if (device->updateStateBlock != device->stateBlock
6576                         && device->updateStateBlock->streamSource[i] == (IWineD3DBuffer *)resource)
6577                 {
6578                     ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6579                             resource, device->updateStateBlock, i);
6580                     device->updateStateBlock->streamSource[i] = NULL;
6581                 }
6582
6583             }
6584
6585             if (device->stateBlock && device->stateBlock->pIndexData == (IWineD3DBuffer *)resource)
6586             {
6587                 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6588                         resource, device->stateBlock);
6589                 device->stateBlock->pIndexData =  NULL;
6590             }
6591
6592             if (device->updateStateBlock != device->stateBlock
6593                     && device->updateStateBlock->pIndexData == (IWineD3DBuffer *)resource)
6594             {
6595                 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6596                         resource, device->updateStateBlock);
6597                 device->updateStateBlock->pIndexData =  NULL;
6598             }
6599             break;
6600
6601         default:
6602             break;
6603     }
6604
6605     /* Remove the resource from the resourceStore */
6606     device_resource_remove(device, resource);
6607
6608     TRACE("Resource released.\n");
6609 }
6610
6611 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
6612     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6613     IWineD3DResourceImpl *resource, *cursor;
6614     HRESULT ret;
6615     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
6616
6617     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6618         TRACE("enumerating resource %p\n", resource);
6619         IWineD3DResource_AddRef((IWineD3DResource *) resource);
6620         ret = pCallback((IWineD3DResource *) resource, pData);
6621         if(ret == S_FALSE) {
6622             TRACE("Canceling enumeration\n");
6623             break;
6624         }
6625     }
6626     return WINED3D_OK;
6627 }
6628
6629 static HRESULT WINAPI IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice *iface, HDC dc, IWineD3DSurface **surface)
6630 {
6631     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6632     IWineD3DResourceImpl *resource;
6633
6634     LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry)
6635     {
6636         WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource);
6637         if (type == WINED3DRTYPE_SURFACE)
6638         {
6639             if (((IWineD3DSurfaceImpl *)resource)->hDC == dc)
6640             {
6641                 TRACE("Found surface %p for dc %p.\n", resource, dc);
6642                 *surface = (IWineD3DSurface *)resource;
6643                 return WINED3D_OK;
6644             }
6645         }
6646     }
6647
6648     return WINED3DERR_INVALIDCALL;
6649 }
6650
6651 /**********************************************************
6652  * IWineD3DDevice VTbl follows
6653  **********************************************************/
6654
6655 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6656 {
6657     /*** IUnknown methods ***/
6658     IWineD3DDeviceImpl_QueryInterface,
6659     IWineD3DDeviceImpl_AddRef,
6660     IWineD3DDeviceImpl_Release,
6661     /*** IWineD3DDevice methods ***/
6662     /*** Creation methods**/
6663     IWineD3DDeviceImpl_CreateBuffer,
6664     IWineD3DDeviceImpl_CreateVertexBuffer,
6665     IWineD3DDeviceImpl_CreateIndexBuffer,
6666     IWineD3DDeviceImpl_CreateStateBlock,
6667     IWineD3DDeviceImpl_CreateSurface,
6668     IWineD3DDeviceImpl_CreateRendertargetView,
6669     IWineD3DDeviceImpl_CreateTexture,
6670     IWineD3DDeviceImpl_CreateVolumeTexture,
6671     IWineD3DDeviceImpl_CreateVolume,
6672     IWineD3DDeviceImpl_CreateCubeTexture,
6673     IWineD3DDeviceImpl_CreateQuery,
6674     IWineD3DDeviceImpl_CreateSwapChain,
6675     IWineD3DDeviceImpl_CreateVertexDeclaration,
6676     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
6677     IWineD3DDeviceImpl_CreateVertexShader,
6678     IWineD3DDeviceImpl_CreateGeometryShader,
6679     IWineD3DDeviceImpl_CreatePixelShader,
6680     IWineD3DDeviceImpl_CreatePalette,
6681     /*** Odd functions **/
6682     IWineD3DDeviceImpl_Init3D,
6683     IWineD3DDeviceImpl_InitGDI,
6684     IWineD3DDeviceImpl_Uninit3D,
6685     IWineD3DDeviceImpl_UninitGDI,
6686     IWineD3DDeviceImpl_SetMultithreaded,
6687     IWineD3DDeviceImpl_EvictManagedResources,
6688     IWineD3DDeviceImpl_GetAvailableTextureMem,
6689     IWineD3DDeviceImpl_GetBackBuffer,
6690     IWineD3DDeviceImpl_GetCreationParameters,
6691     IWineD3DDeviceImpl_GetDeviceCaps,
6692     IWineD3DDeviceImpl_GetDirect3D,
6693     IWineD3DDeviceImpl_GetDisplayMode,
6694     IWineD3DDeviceImpl_SetDisplayMode,
6695     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6696     IWineD3DDeviceImpl_GetRasterStatus,
6697     IWineD3DDeviceImpl_GetSwapChain,
6698     IWineD3DDeviceImpl_Reset,
6699     IWineD3DDeviceImpl_SetDialogBoxMode,
6700     IWineD3DDeviceImpl_SetCursorProperties,
6701     IWineD3DDeviceImpl_SetCursorPosition,
6702     IWineD3DDeviceImpl_ShowCursor,
6703     /*** Getters and setters **/
6704     IWineD3DDeviceImpl_SetClipPlane,
6705     IWineD3DDeviceImpl_GetClipPlane,
6706     IWineD3DDeviceImpl_SetClipStatus,
6707     IWineD3DDeviceImpl_GetClipStatus,
6708     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6709     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6710     IWineD3DDeviceImpl_SetDepthStencilSurface,
6711     IWineD3DDeviceImpl_GetDepthStencilSurface,
6712     IWineD3DDeviceImpl_SetGammaRamp,
6713     IWineD3DDeviceImpl_GetGammaRamp,
6714     IWineD3DDeviceImpl_SetIndexBuffer,
6715     IWineD3DDeviceImpl_GetIndexBuffer,
6716     IWineD3DDeviceImpl_SetBaseVertexIndex,
6717     IWineD3DDeviceImpl_GetBaseVertexIndex,
6718     IWineD3DDeviceImpl_SetLight,
6719     IWineD3DDeviceImpl_GetLight,
6720     IWineD3DDeviceImpl_SetLightEnable,
6721     IWineD3DDeviceImpl_GetLightEnable,
6722     IWineD3DDeviceImpl_SetMaterial,
6723     IWineD3DDeviceImpl_GetMaterial,
6724     IWineD3DDeviceImpl_SetNPatchMode,
6725     IWineD3DDeviceImpl_GetNPatchMode,
6726     IWineD3DDeviceImpl_SetPaletteEntries,
6727     IWineD3DDeviceImpl_GetPaletteEntries,
6728     IWineD3DDeviceImpl_SetPixelShader,
6729     IWineD3DDeviceImpl_GetPixelShader,
6730     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6731     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6732     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6733     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6734     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6735     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6736     IWineD3DDeviceImpl_SetRenderState,
6737     IWineD3DDeviceImpl_GetRenderState,
6738     IWineD3DDeviceImpl_SetRenderTarget,
6739     IWineD3DDeviceImpl_GetRenderTarget,
6740     IWineD3DDeviceImpl_SetFrontBackBuffers,
6741     IWineD3DDeviceImpl_SetSamplerState,
6742     IWineD3DDeviceImpl_GetSamplerState,
6743     IWineD3DDeviceImpl_SetScissorRect,
6744     IWineD3DDeviceImpl_GetScissorRect,
6745     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6746     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6747     IWineD3DDeviceImpl_SetStreamSource,
6748     IWineD3DDeviceImpl_GetStreamSource,
6749     IWineD3DDeviceImpl_SetStreamSourceFreq,
6750     IWineD3DDeviceImpl_GetStreamSourceFreq,
6751     IWineD3DDeviceImpl_SetTexture,
6752     IWineD3DDeviceImpl_GetTexture,
6753     IWineD3DDeviceImpl_SetTextureStageState,
6754     IWineD3DDeviceImpl_GetTextureStageState,
6755     IWineD3DDeviceImpl_SetTransform,
6756     IWineD3DDeviceImpl_GetTransform,
6757     IWineD3DDeviceImpl_SetVertexDeclaration,
6758     IWineD3DDeviceImpl_GetVertexDeclaration,
6759     IWineD3DDeviceImpl_SetVertexShader,
6760     IWineD3DDeviceImpl_GetVertexShader,
6761     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6762     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6763     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6764     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6765     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6766     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6767     IWineD3DDeviceImpl_SetViewport,
6768     IWineD3DDeviceImpl_GetViewport,
6769     IWineD3DDeviceImpl_MultiplyTransform,
6770     IWineD3DDeviceImpl_ValidateDevice,
6771     IWineD3DDeviceImpl_ProcessVertices,
6772     /*** State block ***/
6773     IWineD3DDeviceImpl_BeginStateBlock,
6774     IWineD3DDeviceImpl_EndStateBlock,
6775     /*** Scene management ***/
6776     IWineD3DDeviceImpl_BeginScene,
6777     IWineD3DDeviceImpl_EndScene,
6778     IWineD3DDeviceImpl_Present,
6779     IWineD3DDeviceImpl_Clear,
6780     IWineD3DDeviceImpl_ClearRendertargetView,
6781     /*** Drawing ***/
6782     IWineD3DDeviceImpl_SetPrimitiveType,
6783     IWineD3DDeviceImpl_GetPrimitiveType,
6784     IWineD3DDeviceImpl_DrawPrimitive,
6785     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6786     IWineD3DDeviceImpl_DrawPrimitiveUP,
6787     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6788     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6789     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
6790     IWineD3DDeviceImpl_DrawRectPatch,
6791     IWineD3DDeviceImpl_DrawTriPatch,
6792     IWineD3DDeviceImpl_DeletePatch,
6793     IWineD3DDeviceImpl_ColorFill,
6794     IWineD3DDeviceImpl_UpdateTexture,
6795     IWineD3DDeviceImpl_UpdateSurface,
6796     IWineD3DDeviceImpl_GetFrontBufferData,
6797     /*** object tracking ***/
6798     IWineD3DDeviceImpl_EnumResources,
6799     IWineD3DDeviceImpl_GetSurfaceFromDC,
6800     IWineD3DDeviceImpl_AcquireFocusWindow,
6801     IWineD3DDeviceImpl_ReleaseFocusWindow,
6802 };
6803
6804 HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d,
6805         UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags,
6806         IWineD3DDeviceParent *device_parent)
6807 {
6808     struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
6809     const struct fragment_pipeline *fragment_pipeline;
6810     struct shader_caps shader_caps;
6811     struct fragment_caps ffp_caps;
6812     WINED3DDISPLAYMODE mode;
6813     unsigned int i;
6814     HRESULT hr;
6815
6816     device->lpVtbl = &IWineD3DDevice_Vtbl;
6817     device->ref = 1;
6818     device->wined3d = (IWineD3D *)wined3d;
6819     IWineD3D_AddRef(device->wined3d);
6820     device->adapter = wined3d->adapter_count ? adapter : NULL;
6821     device->device_parent = device_parent;
6822     list_init(&device->resources);
6823     list_init(&device->shaders);
6824
6825     device->surface_alignment = wined3d->dxVersion == 7 ? DDRAW_PITCH_ALIGNMENT : D3D8_PITCH_ALIGNMENT;
6826     device->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
6827
6828     /* Get the initial screen setup for ddraw. */
6829     hr = IWineD3D_GetAdapterDisplayMode((IWineD3D *)wined3d, adapter_idx, &mode);
6830     if (FAILED(hr))
6831     {
6832         ERR("Failed to get the adapter's display mode, hr %#x.\n", hr);
6833         IWineD3D_Release(device->wined3d);
6834         return hr;
6835     }
6836     device->ddraw_width = mode.Width;
6837     device->ddraw_height = mode.Height;
6838     device->ddraw_format = mode.Format;
6839
6840     /* Save the creation parameters. */
6841     device->createParms.AdapterOrdinal = adapter_idx;
6842     device->createParms.DeviceType = device_type;
6843     device->createParms.hFocusWindow = focus_window;
6844     device->createParms.BehaviorFlags = flags;
6845
6846     device->devType = device_type;
6847     for (i = 0; i < PATCHMAP_SIZE; ++i) list_init(&device->patches[i]);
6848
6849     select_shader_mode(&adapter->gl_info, &device->ps_selected_mode, &device->vs_selected_mode);
6850     device->shader_backend = adapter->shader_backend;
6851
6852     if (device->shader_backend)
6853     {
6854         device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
6855         device->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
6856         device->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
6857         device->vs_clipping = shader_caps.VSClipping;
6858     }
6859     fragment_pipeline = adapter->fragment_pipe;
6860     device->frag_pipe = fragment_pipeline;
6861     if (fragment_pipeline)
6862     {
6863         fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
6864         device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
6865
6866         hr = compile_state_table(device->StateTable, device->multistate_funcs, &adapter->gl_info,
6867                                  ffp_vertexstate_template, fragment_pipeline, misc_state_template);
6868         if (FAILED(hr))
6869         {
6870             ERR("Failed to compile state table, hr %#x.\n", hr);
6871             IWineD3D_Release(device->wined3d);
6872             return hr;
6873         }
6874     }
6875     device->blitter = adapter->blitter;
6876
6877     return WINED3D_OK;
6878 }
6879
6880
6881 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6882     DWORD rep = This->StateTable[state].representative;
6883     struct wined3d_context *context;
6884     DWORD idx;
6885     BYTE shift;
6886     UINT i;
6887
6888     for(i = 0; i < This->numContexts; i++) {
6889         context = This->contexts[i];
6890         if(isStateDirty(context, rep)) continue;
6891
6892         context->dirtyArray[context->numDirtyEntries++] = rep;
6893         idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
6894         shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
6895         context->isStateDirty[idx] |= (1 << shift);
6896     }
6897 }
6898
6899 void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height)
6900 {
6901     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
6902     *width = context->current_rt->pow2Width;
6903     *height = context->current_rt->pow2Height;
6904 }
6905
6906 void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height)
6907 {
6908     IWineD3DSwapChainImpl *swapchain = context->swapchain;
6909     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
6910      * current context's drawable, which is the size of the back buffer of the swapchain
6911      * the active context belongs to. */
6912     *width = swapchain->presentParms.BackBufferWidth;
6913     *height = swapchain->presentParms.BackBufferHeight;
6914 }
6915
6916 LRESULT device_process_message(IWineD3DDeviceImpl *device, HWND window,
6917         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
6918 {
6919     if (device->filter_messages)
6920     {
6921         TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
6922                 window, message, wparam, lparam);
6923         return DefWindowProcW(window, message, wparam, lparam);
6924     }
6925
6926     if (message == WM_DESTROY)
6927     {
6928         TRACE("unregister window %p.\n", window);
6929         wined3d_unregister_window(window);
6930
6931         if (device->focus_window == window) device->focus_window = NULL;
6932         else ERR("Window %p is not the focus window for device %p.\n", window, device);
6933     }
6934
6935     return CallWindowProcW(proc, window, message, wparam, lparam);
6936 }