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