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