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