user32: Use the stored color and mask bitmaps instead of the raw bits in GetIconInfo.
[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         IWineD3DSurface_ModifyLocation((IWineD3DSurface *)depth_stencil, SFLAG_INDRAWABLE, TRUE);
4487
4488         glDepthMask(GL_TRUE);
4489         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4490         glClearDepth(Z);
4491         checkGLcall("glClearDepth");
4492         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4493     }
4494
4495     if (Flags & WINED3DCLEAR_TARGET)
4496     {
4497         IWineD3DSurface_ModifyLocation((IWineD3DSurface *)target, SFLAG_INDRAWABLE, TRUE);
4498
4499         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4500         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
4501         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
4502         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
4503         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
4504         glClearColor(D3DCOLOR_R(Color), D3DCOLOR_G(Color), D3DCOLOR_B(Color), D3DCOLOR_A(Color));
4505         checkGLcall("glClearColor");
4506         glMask = glMask | GL_COLOR_BUFFER_BIT;
4507     }
4508
4509     if (!clear_rect)
4510     {
4511         if (context->render_offscreen)
4512         {
4513             glScissor(draw_rect.left, draw_rect.top,
4514                     draw_rect.right - draw_rect.left, draw_rect.bottom - draw_rect.top);
4515         }
4516         else
4517         {
4518             glScissor(draw_rect.left, drawable_height - draw_rect.bottom,
4519                         draw_rect.right - draw_rect.left, draw_rect.bottom - draw_rect.top);
4520         }
4521         checkGLcall("glScissor");
4522         glClear(glMask);
4523         checkGLcall("glClear");
4524     }
4525     else
4526     {
4527         RECT current_rect;
4528
4529         /* Now process each rect in turn. */
4530         for (i = 0; i < Count; ++i)
4531         {
4532             /* Note gl uses lower left, width/height */
4533             IntersectRect(&current_rect, &draw_rect, &clear_rect[i]);
4534
4535             TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
4536                     wine_dbgstr_rect(&clear_rect[i]),
4537                     wine_dbgstr_rect(&current_rect));
4538
4539             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4540              * The rectangle is not cleared, no error is returned, but further rectanlges are
4541              * still cleared if they are valid. */
4542             if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
4543             {
4544                 TRACE("Rectangle with negative dimensions, ignoring.\n");
4545                 continue;
4546             }
4547
4548             if (context->render_offscreen)
4549             {
4550                 glScissor(current_rect.left, current_rect.top,
4551                         current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
4552             }
4553             else
4554             {
4555                 glScissor(current_rect.left, drawable_height - current_rect.bottom,
4556                           current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
4557             }
4558             checkGLcall("glScissor");
4559
4560             glClear(glMask);
4561             checkGLcall("glClear");
4562         }
4563     }
4564
4565     LEAVE_GL();
4566
4567     if (wined3d_settings.strict_draw_ordering || ((target->Flags & SFLAG_SWAPCHAIN)
4568             && ((IWineD3DSwapChainImpl *)target->container)->front_buffer == target))
4569         wglFlush(); /* Flush to ensure ordering across contexts. */
4570
4571     context_release(context);
4572
4573     return WINED3D_OK;
4574 }
4575
4576 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count,
4577         const WINED3DRECT *pRects, DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil)
4578 {
4579     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4580
4581     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
4582           Count, pRects, Flags, Color, Z, Stencil);
4583
4584     if (Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && !This->depth_stencil)
4585     {
4586         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4587         /* TODO: What about depth stencil buffers without stencil bits? */
4588         return WINED3DERR_INVALIDCALL;
4589     }
4590
4591     return IWineD3DDeviceImpl_ClearSurface(This, This->render_targets[0], Count, pRects, Flags, Color, Z, Stencil);
4592 }
4593
4594 /*****
4595  * Drawing functions
4596  *****/
4597
4598 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
4599         WINED3DPRIMITIVETYPE primitive_type)
4600 {
4601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602
4603     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
4604
4605     This->updateStateBlock->changed.primitive_type = TRUE;
4606     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
4607 }
4608
4609 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
4610         WINED3DPRIMITIVETYPE *primitive_type)
4611 {
4612     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4613
4614     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
4615
4616     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
4617
4618     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
4619 }
4620
4621 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
4622 {
4623     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4624
4625     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
4626
4627     if(!This->stateBlock->vertexDecl) {
4628         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4629         return WINED3DERR_INVALIDCALL;
4630     }
4631
4632     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4633     if(This->stateBlock->streamIsUP) {
4634         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4635         This->stateBlock->streamIsUP = FALSE;
4636     }
4637
4638     if(This->stateBlock->loadBaseVertexIndex != 0) {
4639         This->stateBlock->loadBaseVertexIndex = 0;
4640         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4641     }
4642     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4643     drawPrimitive(iface, vertex_count, StartVertex /* start_idx */, 0 /* indxSize */, NULL /* indxData */);
4644     return WINED3D_OK;
4645 }
4646
4647 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, UINT startIndex, UINT index_count)
4648 {
4649     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4650     UINT                 idxStride = 2;
4651     IWineD3DBuffer *pIB;
4652     GLuint vbo;
4653
4654     pIB = This->stateBlock->pIndexData;
4655     if (!pIB) {
4656         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4657          * without an index buffer set. (The first time at least...)
4658          * D3D8 simply dies, but I doubt it can do much harm to return
4659          * D3DERR_INVALIDCALL there as well. */
4660         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4661         return WINED3DERR_INVALIDCALL;
4662     }
4663
4664     if(!This->stateBlock->vertexDecl) {
4665         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4666         return WINED3DERR_INVALIDCALL;
4667     }
4668
4669     if(This->stateBlock->streamIsUP) {
4670         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4671         This->stateBlock->streamIsUP = FALSE;
4672     }
4673     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
4674
4675     TRACE("(%p) : startIndex %u, index count %u.\n", This, startIndex, index_count);
4676
4677     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
4678         idxStride = 2;
4679     } else {
4680         idxStride = 4;
4681     }
4682
4683     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4684         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4685         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4686     }
4687
4688     drawPrimitive(iface, index_count, startIndex, idxStride,
4689             vbo ? NULL : ((struct wined3d_buffer *)pIB)->resource.allocatedMemory);
4690
4691     return WINED3D_OK;
4692 }
4693
4694 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
4695         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4696 {
4697     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4698     IWineD3DBuffer *vb;
4699
4700     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4701             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
4702
4703     if(!This->stateBlock->vertexDecl) {
4704         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4705         return WINED3DERR_INVALIDCALL;
4706     }
4707
4708     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4709     vb = This->stateBlock->streamSource[0];
4710     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4711     if (vb) IWineD3DBuffer_Release(vb);
4712     This->stateBlock->streamOffset[0] = 0;
4713     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4714     This->stateBlock->streamIsUP = TRUE;
4715     This->stateBlock->loadBaseVertexIndex = 0;
4716
4717     /* TODO: Only mark dirty if drawing from a different UP address */
4718     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4719
4720     drawPrimitive(iface, vertex_count, 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */);
4721
4722     /* MSDN specifies stream zero settings must be set to NULL */
4723     This->stateBlock->streamStride[0] = 0;
4724     This->stateBlock->streamSource[0] = NULL;
4725
4726     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4727      * the new stream sources or use UP drawing again
4728      */
4729     return WINED3D_OK;
4730 }
4731
4732 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
4733         UINT index_count, const void *pIndexData, WINED3DFORMAT IndexDataFormat,
4734         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4735 {
4736     int                 idxStride;
4737     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738     IWineD3DBuffer *vb;
4739     IWineD3DBuffer *ib;
4740
4741     TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4742             This, index_count, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4743
4744     if(!This->stateBlock->vertexDecl) {
4745         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4746         return WINED3DERR_INVALIDCALL;
4747     }
4748
4749     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
4750         idxStride = 2;
4751     } else {
4752         idxStride = 4;
4753     }
4754
4755     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4756     vb = This->stateBlock->streamSource[0];
4757     This->stateBlock->streamSource[0] = (IWineD3DBuffer *)pVertexStreamZeroData;
4758     if (vb) IWineD3DBuffer_Release(vb);
4759     This->stateBlock->streamIsUP = TRUE;
4760     This->stateBlock->streamOffset[0] = 0;
4761     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4762
4763     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4764     This->stateBlock->baseVertexIndex = 0;
4765     This->stateBlock->loadBaseVertexIndex = 0;
4766     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4767     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4768     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4769
4770     drawPrimitive(iface, index_count, 0 /* start_idx */, idxStride, pIndexData);
4771
4772     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4773     This->stateBlock->streamSource[0] = NULL;
4774     This->stateBlock->streamStride[0] = 0;
4775     ib = This->stateBlock->pIndexData;
4776     if(ib) {
4777         IWineD3DBuffer_Release(ib);
4778         This->stateBlock->pIndexData = NULL;
4779     }
4780     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4781      * SetStreamSource to specify a vertex buffer
4782      */
4783
4784     return WINED3D_OK;
4785 }
4786
4787 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
4788         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
4789 {
4790     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4791
4792     /* Mark the state dirty until we have nicer tracking
4793      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4794      * that value.
4795      */
4796     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4797     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4798     This->stateBlock->baseVertexIndex = 0;
4799     This->up_strided = DrawPrimStrideData;
4800     drawPrimitive(iface, vertex_count, 0, 0, NULL);
4801     This->up_strided = NULL;
4802     return WINED3D_OK;
4803 }
4804
4805 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
4806         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
4807         UINT NumVertices, const void *pIndexData, WINED3DFORMAT IndexDataFormat)
4808 {
4809     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4810     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
4811
4812     /* Mark the state dirty until we have nicer tracking
4813      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4814      * that value.
4815      */
4816     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4817     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4818     This->stateBlock->streamIsUP = TRUE;
4819     This->stateBlock->baseVertexIndex = 0;
4820     This->up_strided = DrawPrimStrideData;
4821     drawPrimitive(iface, vertex_count, 0 /* start_idx */, idxSize, pIndexData);
4822     This->up_strided = NULL;
4823     return WINED3D_OK;
4824 }
4825
4826 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
4827 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface,
4828         IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume)
4829 {
4830     WINED3DLOCKED_BOX src;
4831     WINED3DLOCKED_BOX dst;
4832     HRESULT hr;
4833
4834     TRACE("iface %p, src_volume %p, dst_volume %p.\n",
4835             iface, pSourceVolume, pDestinationVolume);
4836
4837     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
4838      * dirtification to improve loading performance.
4839      */
4840     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
4841     if(FAILED(hr)) return hr;
4842     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
4843     if(FAILED(hr)) {
4844     IWineD3DVolume_UnlockBox(pSourceVolume);
4845             return hr;
4846     }
4847
4848     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
4849
4850     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
4851     if(FAILED(hr)) {
4852         IWineD3DVolume_UnlockBox(pSourceVolume);
4853     } else {
4854         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
4855     }
4856     return hr;
4857 }
4858
4859 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice *iface,
4860         IWineD3DBaseTexture *src_texture, IWineD3DBaseTexture *dst_texture)
4861 {
4862     unsigned int level_count, i;
4863     WINED3DRESOURCETYPE type;
4864     HRESULT hr;
4865
4866     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
4867
4868     /* Verify that the source and destination textures are non-NULL. */
4869     if (!src_texture || !dst_texture)
4870     {
4871         WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
4872         return WINED3DERR_INVALIDCALL;
4873     }
4874
4875     if (src_texture == dst_texture)
4876     {
4877         WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
4878         return WINED3DERR_INVALIDCALL;
4879     }
4880
4881     /* Verify that the source and destination textures are the same type. */
4882     type = IWineD3DBaseTexture_GetType(src_texture);
4883     if (IWineD3DBaseTexture_GetType(dst_texture) != type)
4884     {
4885         WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
4886         return WINED3DERR_INVALIDCALL;
4887     }
4888
4889     /* Check that both textures have the identical numbers of levels. */
4890     level_count = IWineD3DBaseTexture_GetLevelCount(src_texture);
4891     if (IWineD3DBaseTexture_GetLevelCount(dst_texture) != level_count)
4892     {
4893         WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
4894         return WINED3DERR_INVALIDCALL;
4895     }
4896
4897     /* Make sure that the destination texture is loaded. */
4898     ((IWineD3DBaseTextureImpl *)dst_texture)->baseTexture.internal_preload(dst_texture, SRGB_RGB);
4899
4900     /* Update every surface level of the texture. */
4901     switch (type)
4902     {
4903         case WINED3DRTYPE_TEXTURE:
4904         {
4905             IWineD3DSurface *src_surface;
4906             IWineD3DSurface *dst_surface;
4907
4908             for (i = 0; i < level_count; ++i)
4909             {
4910                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)src_texture, i, &src_surface);
4911                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)dst_texture, i, &dst_surface);
4912                 hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4913                 IWineD3DSurface_Release(dst_surface);
4914                 IWineD3DSurface_Release(src_surface);
4915                 if (FAILED(hr))
4916                 {
4917                     WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4918                     return hr;
4919                 }
4920             }
4921             break;
4922         }
4923
4924         case WINED3DRTYPE_CUBETEXTURE:
4925         {
4926             IWineD3DSurface *src_surface;
4927             IWineD3DSurface *dst_surface;
4928             WINED3DCUBEMAP_FACES face;
4929
4930             for (i = 0; i < level_count; ++i)
4931             {
4932                 /* Update each cube face. */
4933                 for (face = WINED3DCUBEMAP_FACE_POSITIVE_X; face <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++face)
4934                 {
4935                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)src_texture,
4936                             face, i, &src_surface);
4937                     if (FAILED(hr)) ERR("Failed to get src cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4938                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)dst_texture,
4939                             face, i, &dst_surface);
4940                     if (FAILED(hr)) ERR("Failed to get dst cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4941                     hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4942                     IWineD3DSurface_Release(dst_surface);
4943                     IWineD3DSurface_Release(src_surface);
4944                     if (FAILED(hr))
4945                     {
4946                         WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4947                         return hr;
4948                     }
4949                 }
4950             }
4951             break;
4952         }
4953
4954         case WINED3DRTYPE_VOLUMETEXTURE:
4955         {
4956             IWineD3DVolume *src_volume;
4957             IWineD3DVolume *dst_volume;
4958
4959             for (i = 0; i < level_count; ++i)
4960             {
4961                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)src_texture, i, &src_volume);
4962                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)dst_texture, i, &dst_volume);
4963                 hr = IWineD3DDeviceImpl_UpdateVolume(iface, src_volume, dst_volume);
4964                 IWineD3DVolume_Release(dst_volume);
4965                 IWineD3DVolume_Release(src_volume);
4966                 if (FAILED(hr))
4967                 {
4968                     WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr);
4969                     return hr;
4970                 }
4971             }
4972             break;
4973         }
4974
4975         default:
4976             FIXME("Unsupported texture type %#x.\n", type);
4977             return WINED3DERR_INVALIDCALL;
4978     }
4979
4980     return WINED3D_OK;
4981 }
4982
4983 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4984     IWineD3DSwapChain *swapChain;
4985     HRESULT hr;
4986     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4987     if(hr == WINED3D_OK) {
4988         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4989                 IWineD3DSwapChain_Release(swapChain);
4990     }
4991     return hr;
4992 }
4993
4994 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4995     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4996     IWineD3DBaseTextureImpl *texture;
4997     DWORD i;
4998
4999     TRACE("(%p) : %p\n", This, pNumPasses);
5000
5001     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5002         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE) {
5003             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5004             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5005         }
5006         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE) {
5007             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5008             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5009         }
5010
5011         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5012         if (!texture || texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5013
5014         if(This->stateBlock->samplerState[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT) {
5015             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5016             return E_FAIL;
5017         }
5018         if(This->stateBlock->samplerState[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT) {
5019             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5020             return E_FAIL;
5021         }
5022         if(This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE &&
5023            This->stateBlock->samplerState[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT /* sic! */) {
5024             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5025             return E_FAIL;
5026         }
5027     }
5028
5029     /* return a sensible default */
5030     *pNumPasses = 1;
5031
5032     TRACE("returning D3D_OK\n");
5033     return WINED3D_OK;
5034 }
5035
5036 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5037 {
5038     int i;
5039
5040     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
5041     {
5042         IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5043         if (texture && (texture->resource.format_desc->format == WINED3DFMT_P8_UINT
5044                 || texture->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM))
5045         {
5046             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5047         }
5048     }
5049 }
5050
5051 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5052     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5053     int j;
5054     UINT NewSize;
5055     PALETTEENTRY **palettes;
5056
5057     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5058
5059     if (PaletteNumber >= MAX_PALETTES) {
5060         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5061         return WINED3DERR_INVALIDCALL;
5062     }
5063
5064     if (PaletteNumber >= This->NumberOfPalettes) {
5065         NewSize = This->NumberOfPalettes;
5066         do {
5067            NewSize *= 2;
5068         } while(PaletteNumber >= NewSize);
5069         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5070         if (!palettes) {
5071             ERR("Out of memory!\n");
5072             return E_OUTOFMEMORY;
5073         }
5074         This->palettes = palettes;
5075         This->NumberOfPalettes = NewSize;
5076     }
5077
5078     if (!This->palettes[PaletteNumber]) {
5079         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5080         if (!This->palettes[PaletteNumber]) {
5081             ERR("Out of memory!\n");
5082             return E_OUTOFMEMORY;
5083         }
5084     }
5085
5086     for (j = 0; j < 256; ++j) {
5087         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5088         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5089         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5090         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5091     }
5092     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5093     TRACE("(%p) : returning\n", This);
5094     return WINED3D_OK;
5095 }
5096
5097 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5098     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5099     int j;
5100     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5101     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5102         /* What happens in such situation isn't documented; Native seems to silently abort
5103            on such conditions. Return Invalid Call. */
5104         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5105         return WINED3DERR_INVALIDCALL;
5106     }
5107     for (j = 0; j < 256; ++j) {
5108         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5109         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5110         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5111         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5112     }
5113     TRACE("(%p) : returning\n", This);
5114     return WINED3D_OK;
5115 }
5116
5117 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5118     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5119     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5120     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5121        (tested with reference rasterizer). Return Invalid Call. */
5122     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5123         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5124         return WINED3DERR_INVALIDCALL;
5125     }
5126     /*TODO: stateblocks */
5127     if (This->currentPalette != PaletteNumber) {
5128         This->currentPalette = PaletteNumber;
5129         dirtify_p8_texture_samplers(This);
5130     }
5131     TRACE("(%p) : returning\n", This);
5132     return WINED3D_OK;
5133 }
5134
5135 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5136     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5137     if (PaletteNumber == NULL) {
5138         WARN("(%p) : returning Invalid Call\n", This);
5139         return WINED3DERR_INVALIDCALL;
5140     }
5141     /*TODO: stateblocks */
5142     *PaletteNumber = This->currentPalette;
5143     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5144     return WINED3D_OK;
5145 }
5146
5147 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5148     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5149     static BOOL warned;
5150     if (!warned)
5151     {
5152         FIXME("(%p) : stub\n", This);
5153         warned = TRUE;
5154     }
5155
5156     This->softwareVertexProcessing = bSoftware;
5157     return WINED3D_OK;
5158 }
5159
5160
5161 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5162     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5163     static BOOL warned;
5164     if (!warned)
5165     {
5166         FIXME("(%p) : stub\n", This);
5167         warned = TRUE;
5168     }
5169     return This->softwareVertexProcessing;
5170 }
5171
5172 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface,
5173         UINT swapchain_idx, WINED3DRASTER_STATUS *raster_status)
5174 {
5175     IWineD3DSwapChain *swapchain;
5176     HRESULT hr;
5177
5178     TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
5179             iface, swapchain_idx, raster_status);
5180
5181     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5182     if (FAILED(hr))
5183     {
5184         WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx, hr);
5185         return hr;
5186     }
5187
5188     hr = IWineD3DSwapChain_GetRasterStatus(swapchain, raster_status);
5189     IWineD3DSwapChain_Release(swapchain);
5190     if (FAILED(hr))
5191     {
5192         WARN("Failed to get raster status, hr %#x.\n", hr);
5193         return hr;
5194     }
5195
5196     return WINED3D_OK;
5197 }
5198
5199 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments)
5200 {
5201     static BOOL warned;
5202     if(nSegments != 0.0f) {
5203         if (!warned)
5204         {
5205             FIXME("iface %p, nSegments %.8e stub!\n", iface, nSegments);
5206             warned = TRUE;
5207         }
5208     }
5209     return WINED3D_OK;
5210 }
5211
5212 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface)
5213 {
5214     static BOOL warned;
5215     if (!warned)
5216     {
5217         FIXME("iface %p stub!\n", iface);
5218         warned = TRUE;
5219     }
5220     return 0.0f;
5221 }
5222
5223 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
5224         IWineD3DSurface *src_surface, const RECT *src_rect,
5225         IWineD3DSurface *dst_surface, const POINT *dst_point)
5226 {
5227     IWineD3DSurfaceImpl *src_impl = (IWineD3DSurfaceImpl *)src_surface;
5228     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)dst_surface;
5229     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5230     const struct wined3d_format_desc *src_format;
5231     const struct wined3d_format_desc *dst_format;
5232     struct wined3d_context *context;
5233     const unsigned char *data;
5234     UINT update_w, update_h;
5235     CONVERT_TYPES convert;
5236     UINT src_w, src_h;
5237     UINT dst_x, dst_y;
5238     DWORD sampler;
5239     struct wined3d_format_desc desc;
5240
5241     TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
5242             iface, src_surface, wine_dbgstr_rect(src_rect),
5243             dst_surface, wine_dbgstr_point(dst_point));
5244
5245     if (src_impl->resource.pool != WINED3DPOOL_SYSTEMMEM || dst_impl->resource.pool != WINED3DPOOL_DEFAULT)
5246     {
5247         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
5248                 src_surface, dst_surface);
5249         return WINED3DERR_INVALIDCALL;
5250     }
5251
5252     src_format = src_impl->resource.format_desc;
5253     dst_format = dst_impl->resource.format_desc;
5254
5255     if (src_format->format != dst_format->format)
5256     {
5257         WARN("Source and destination surfaces should have the same format.\n");
5258         return WINED3DERR_INVALIDCALL;
5259     }
5260
5261     dst_x = dst_point ? dst_point->x : 0;
5262     dst_y = dst_point ? dst_point->y : 0;
5263
5264     /* This call loads the OpenGL surface directly, instead of copying the
5265      * surface to the destination's sysmem copy. If surface conversion is
5266      * needed, use BltFast instead to copy in sysmem and use regular surface
5267      * loading. */
5268     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &desc, &convert);
5269     if (convert != NO_CONVERSION || desc.convert)
5270         return IWineD3DSurface_BltFast(dst_surface, dst_x, dst_y, src_surface, src_rect, 0);
5271
5272     context = context_acquire(This, NULL);
5273
5274     ENTER_GL();
5275     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5276     checkGLcall("glActiveTextureARB");
5277     LEAVE_GL();
5278
5279     /* Make sure the surface is loaded and up to date */
5280     surface_internal_preload(dst_impl, SRGB_RGB);
5281     IWineD3DSurface_BindTexture(dst_surface, FALSE);
5282
5283     src_w = src_impl->currentDesc.Width;
5284     src_h = src_impl->currentDesc.Height;
5285     update_w = src_rect ? src_rect->right - src_rect->left : src_w;
5286     update_h = src_rect ? src_rect->bottom - src_rect->top : src_h;
5287
5288     data = IWineD3DSurface_GetData(src_surface);
5289     if (!data) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n");
5290
5291     ENTER_GL();
5292
5293     if (dst_format->Flags & WINED3DFMT_FLAG_COMPRESSED)
5294     {
5295         UINT row_length = (update_w / src_format->block_width) * src_format->block_byte_count;
5296         UINT row_count = update_h / src_format->block_height;
5297         UINT src_pitch = IWineD3DSurface_GetPitch(src_surface);
5298
5299         if (src_rect)
5300         {
5301             data += (src_rect->top / src_format->block_height) * src_pitch;
5302             data += (src_rect->left / src_format->block_width) * src_format->block_byte_count;
5303         }
5304
5305         TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
5306                 "format %#x, image_size %#x, data %p.\n", dst_impl->texture_target, dst_impl->texture_level,
5307                 dst_x, dst_y, update_w, update_h, dst_format->glFormat, row_count * row_length, data);
5308
5309         if (row_length == src_pitch)
5310         {
5311             GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5312                     dst_x, dst_y, update_w, update_h, dst_format->glInternal, row_count * row_length, data));
5313         }
5314         else
5315         {
5316             UINT row, y;
5317
5318             /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
5319              * can't use the unpack row length like below. */
5320             for (row = 0, y = dst_y; row < row_count; ++row)
5321             {
5322                 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5323                         dst_x, y, update_w, src_format->block_height, dst_format->glInternal, row_length, data));
5324                 y += src_format->block_height;
5325                 data += src_pitch;
5326             }
5327         }
5328         checkGLcall("glCompressedTexSubImage2DARB");
5329     }
5330     else
5331     {
5332         if (src_rect)
5333         {
5334             data += src_rect->top * src_w * src_format->byte_count;
5335             data += src_rect->left * src_format->byte_count;
5336         }
5337
5338         TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n",
5339                 dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5340                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5341
5342         glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w);
5343         glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5344                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5345         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
5346         checkGLcall("glTexSubImage2D");
5347     }
5348
5349     LEAVE_GL();
5350     context_release(context);
5351
5352     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INTEXTURE, TRUE);
5353     sampler = This->rev_tex_unit_map[0];
5354     if (sampler != WINED3D_UNMAPPED_STAGE)
5355     {
5356         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5357     }
5358
5359     return WINED3D_OK;
5360 }
5361
5362 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5363     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5364     struct WineD3DRectPatch *patch;
5365     GLenum old_primitive_type;
5366     unsigned int i;
5367     struct list *e;
5368     BOOL found;
5369     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5370
5371     if(!(Handle || pRectPatchInfo)) {
5372         /* TODO: Write a test for the return value, thus the FIXME */
5373         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5374         return WINED3DERR_INVALIDCALL;
5375     }
5376
5377     if(Handle) {
5378         i = PATCHMAP_HASHFUNC(Handle);
5379         found = FALSE;
5380         LIST_FOR_EACH(e, &This->patches[i]) {
5381             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5382             if(patch->Handle == Handle) {
5383                 found = TRUE;
5384                 break;
5385             }
5386         }
5387
5388         if(!found) {
5389             TRACE("Patch does not exist. Creating a new one\n");
5390             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5391             patch->Handle = Handle;
5392             list_add_head(&This->patches[i], &patch->entry);
5393         } else {
5394             TRACE("Found existing patch %p\n", patch);
5395         }
5396     } else {
5397         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5398          * attributes we have to tesselate, read back, and draw. This needs a patch
5399          * management structure instance. Create one.
5400          *
5401          * A possible improvement is to check if a vertex shader is used, and if not directly
5402          * draw the patch.
5403          */
5404         FIXME("Drawing an uncached patch. This is slow\n");
5405         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5406     }
5407
5408     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5409        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5410        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5411         HRESULT hr;
5412         TRACE("Tesselation density or patch info changed, retesselating\n");
5413
5414         if(pRectPatchInfo) {
5415             patch->RectPatchInfo = *pRectPatchInfo;
5416         }
5417         patch->numSegs[0] = pNumSegs[0];
5418         patch->numSegs[1] = pNumSegs[1];
5419         patch->numSegs[2] = pNumSegs[2];
5420         patch->numSegs[3] = pNumSegs[3];
5421
5422         hr = tesselate_rectpatch(This, patch);
5423         if(FAILED(hr)) {
5424             WARN("Patch tesselation failed\n");
5425
5426             /* Do not release the handle to store the params of the patch */
5427             if(!Handle) {
5428                 HeapFree(GetProcessHeap(), 0, patch);
5429             }
5430             return hr;
5431         }
5432     }
5433
5434     This->currentPatch = patch;
5435     old_primitive_type = This->stateBlock->gl_primitive_type;
5436     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5437     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5438     This->stateBlock->gl_primitive_type = old_primitive_type;
5439     This->currentPatch = NULL;
5440
5441     /* Destroy uncached patches */
5442     if(!Handle) {
5443         HeapFree(GetProcessHeap(), 0, patch->mem);
5444         HeapFree(GetProcessHeap(), 0, patch);
5445     }
5446     return WINED3D_OK;
5447 }
5448
5449 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface,
5450         UINT handle, const float *segment_count, const WINED3DTRIPATCH_INFO *patch_info)
5451 {
5452     FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5453             iface, handle, segment_count, patch_info);
5454
5455     return WINED3D_OK;
5456 }
5457
5458 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5459     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5460     int i;
5461     struct WineD3DRectPatch *patch;
5462     struct list *e;
5463     TRACE("(%p) Handle(%d)\n", This, Handle);
5464
5465     i = PATCHMAP_HASHFUNC(Handle);
5466     LIST_FOR_EACH(e, &This->patches[i]) {
5467         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5468         if(patch->Handle == Handle) {
5469             TRACE("Deleting patch %p\n", patch);
5470             list_remove(&patch->entry);
5471             HeapFree(GetProcessHeap(), 0, patch->mem);
5472             HeapFree(GetProcessHeap(), 0, patch);
5473             return WINED3D_OK;
5474         }
5475     }
5476
5477     /* TODO: Write a test for the return value */
5478     FIXME("Attempt to destroy nonexistent patch\n");
5479     return WINED3DERR_INVALIDCALL;
5480 }
5481
5482 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface,
5483         const WINED3DRECT *rect, const float color[4])
5484 {
5485     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5486     struct wined3d_context *context;
5487
5488     if (rect) IWineD3DSurface_LoadLocation((IWineD3DSurface *)surface, SFLAG_INDRAWABLE, NULL);
5489     IWineD3DSurface_ModifyLocation((IWineD3DSurface *)surface, SFLAG_INDRAWABLE, TRUE);
5490
5491     context = context_acquire(This, surface);
5492     context_apply_clear_state(context, This, surface, NULL);
5493
5494     ENTER_GL();
5495
5496     if (rect)
5497     {
5498         if (surface_is_offscreen(surface))
5499             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
5500         else
5501             glScissor(rect->x1, surface->currentDesc.Height - rect->y2,
5502                     rect->x2 - rect->x1, rect->y2 - rect->y1);
5503         checkGLcall("glScissor");
5504     }
5505     else
5506     {
5507         glDisable(GL_SCISSOR_TEST);
5508     }
5509
5510     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5511     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
5512     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
5513     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
5514     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
5515
5516     glClearColor(color[0], color[1], color[2], color[3]);
5517     glClear(GL_COLOR_BUFFER_BIT);
5518     checkGLcall("glClear");
5519
5520     LEAVE_GL();
5521
5522     if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
5523
5524     context_release(context);
5525 }
5526
5527 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface,
5528         IWineD3DSurface *pSurface, const WINED3DRECT *pRect, WINED3DCOLOR color)
5529 {
5530     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5531     WINEDDBLTFX BltFx;
5532
5533     TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, pSurface, pRect, color);
5534
5535     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5536         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5537         return WINED3DERR_INVALIDCALL;
5538     }
5539
5540     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5541         const float c[4] = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)};
5542         color_fill_fbo(iface, surface, pRect, c);
5543         return WINED3D_OK;
5544     } else {
5545         /* Just forward this to the DirectDraw blitting engine */
5546         memset(&BltFx, 0, sizeof(BltFx));
5547         BltFx.dwSize = sizeof(BltFx);
5548         BltFx.u5.dwFillColor = color_convert_argb_to_fmt(color, surface->resource.format_desc->format);
5549         return IWineD3DSurface_Blt(pSurface, (const RECT *)pRect, NULL, NULL,
5550                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
5551     }
5552 }
5553
5554 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
5555         IWineD3DRendertargetView *rendertarget_view, const float color[4])
5556 {
5557     IWineD3DResource *resource;
5558     IWineD3DSurfaceImpl *surface;
5559     HRESULT hr;
5560
5561     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
5562     if (FAILED(hr))
5563     {
5564         ERR("Failed to get resource, hr %#x\n", hr);
5565         return;
5566     }
5567
5568     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
5569     {
5570         FIXME("Only supported on surface resources\n");
5571         IWineD3DResource_Release(resource);
5572         return;
5573     }
5574
5575     surface = (IWineD3DSurfaceImpl *)resource;
5576
5577     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
5578     {
5579         color_fill_fbo(iface, surface, NULL, color);
5580     }
5581     else
5582     {
5583         WINEDDBLTFX BltFx;
5584         WINED3DCOLOR c;
5585
5586         WARN("Converting to WINED3DCOLOR, this might give incorrect results\n");
5587
5588         c = ((DWORD)(color[2] * 255.0f));
5589         c |= ((DWORD)(color[1] * 255.0f)) << 8;
5590         c |= ((DWORD)(color[0] * 255.0f)) << 16;
5591         c |= ((DWORD)(color[3] * 255.0f)) << 24;
5592
5593         /* Just forward this to the DirectDraw blitting engine */
5594         memset(&BltFx, 0, sizeof(BltFx));
5595         BltFx.dwSize = sizeof(BltFx);
5596         BltFx.u5.dwFillColor = color_convert_argb_to_fmt(c, surface->resource.format_desc->format);
5597         hr = IWineD3DSurface_Blt((IWineD3DSurface *)surface, NULL, NULL, NULL,
5598                 WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_POINT);
5599         if (FAILED(hr))
5600         {
5601             ERR("Blt failed, hr %#x\n", hr);
5602         }
5603     }
5604
5605     IWineD3DResource_Release(resource);
5606 }
5607
5608 /* rendertarget and depth stencil functions */
5609 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5610     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5611
5612     if (RenderTargetIndex >= This->adapter->gl_info.limits.buffers)
5613     {
5614         ERR("(%p) : Only %d render targets are supported.\n",
5615                 This, This->adapter->gl_info.limits.buffers);
5616         return WINED3DERR_INVALIDCALL;
5617     }
5618
5619     *ppRenderTarget = (IWineD3DSurface *)This->render_targets[RenderTargetIndex];
5620     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5621     /* Note inc ref on returned surface */
5622     if(*ppRenderTarget != NULL)
5623         IWineD3DSurface_AddRef(*ppRenderTarget);
5624     return WINED3D_OK;
5625 }
5626
5627 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface,
5628         IWineD3DSurface *front, IWineD3DSurface *back)
5629 {
5630     IWineD3DSurfaceImpl *front_impl = (IWineD3DSurfaceImpl *)front;
5631     IWineD3DSurfaceImpl *back_impl = (IWineD3DSurfaceImpl *)back;
5632     IWineD3DSwapChainImpl *swapchain;
5633     HRESULT hr;
5634
5635     TRACE("iface %p, front %p, back %p.\n", iface, front, back);
5636
5637     if (FAILED(hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&swapchain)))
5638     {
5639         ERR("Failed to get the swapchain, hr %#x.\n", hr);
5640         return hr;
5641     }
5642
5643     if (front_impl && !(front_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5644     {
5645         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5646         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5647         return WINED3DERR_INVALIDCALL;
5648     }
5649
5650     if (back_impl)
5651     {
5652         if (!(back_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5653         {
5654             ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5655             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5656             return WINED3DERR_INVALIDCALL;
5657         }
5658
5659         if (!swapchain->back_buffers)
5660         {
5661             swapchain->back_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*swapchain->back_buffers));
5662             if (!swapchain->back_buffers)
5663             {
5664                 ERR("Failed to allocate back buffer array memory.\n");
5665                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5666                 return E_OUTOFMEMORY;
5667             }
5668         }
5669     }
5670
5671     if (swapchain->front_buffer != front_impl)
5672     {
5673         TRACE("Changing the front buffer from %p to %p.\n", swapchain->front_buffer, front_impl);
5674
5675         if (swapchain->front_buffer)
5676         {
5677             IWineD3DSurface_SetContainer((IWineD3DSurface *)swapchain->front_buffer, NULL);
5678             swapchain->front_buffer->Flags &= ~SFLAG_SWAPCHAIN;
5679         }
5680         swapchain->front_buffer = front_impl;
5681
5682         if (front)
5683         {
5684             IWineD3DSurface_SetContainer(front, (IWineD3DBase *)swapchain);
5685             front_impl->Flags |= SFLAG_SWAPCHAIN;
5686         }
5687     }
5688
5689     if (swapchain->back_buffers[0] != back_impl)
5690     {
5691         TRACE("Changing the back buffer from %p to %p.\n", swapchain->back_buffers[0], back_impl);
5692
5693         if (swapchain->back_buffers[0])
5694         {
5695             IWineD3DSurface_SetContainer((IWineD3DSurface *)swapchain->back_buffers[0], NULL);
5696             swapchain->back_buffers[0]->Flags &= ~SFLAG_SWAPCHAIN;
5697         }
5698         swapchain->back_buffers[0] = back_impl;
5699
5700         if (back)
5701         {
5702             swapchain->presentParms.BackBufferWidth = back_impl->currentDesc.Width;
5703             swapchain->presentParms.BackBufferHeight = back_impl->currentDesc.Height;
5704             swapchain->presentParms.BackBufferFormat = back_impl->resource.format_desc->format;
5705             swapchain->presentParms.BackBufferCount = 1;
5706
5707             IWineD3DSurface_SetContainer(back, (IWineD3DBase *)swapchain);
5708             back_impl->Flags |= SFLAG_SWAPCHAIN;
5709         }
5710         else
5711         {
5712             swapchain->presentParms.BackBufferCount = 0;
5713             HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
5714             swapchain->back_buffers = NULL;
5715         }
5716     }
5717
5718     IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5719     return WINED3D_OK;
5720 }
5721
5722 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5723     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5724     *ppZStencilSurface = (IWineD3DSurface *)This->depth_stencil;
5725     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5726
5727     if(*ppZStencilSurface != NULL) {
5728         /* Note inc ref on returned surface */
5729         IWineD3DSurface_AddRef(*ppZStencilSurface);
5730         return WINED3D_OK;
5731     } else {
5732         return WINED3DERR_NOTFOUND;
5733     }
5734 }
5735
5736 void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect_in,
5737         IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, const WINED3DTEXTUREFILTERTYPE filter)
5738 {
5739     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
5740     const struct wined3d_gl_info *gl_info;
5741     struct wined3d_context *context;
5742     GLenum gl_filter;
5743     POINT offset = {0, 0};
5744     RECT src_rect, dst_rect;
5745
5746     TRACE("device %p, src_surface %p, src_rect_in %s, dst_surface %p, dst_rect_in %s, filter %s (0x%08x).\n",
5747             device, src_surface, wine_dbgstr_rect(src_rect_in), dst_surface,
5748             wine_dbgstr_rect(dst_rect_in), debug_d3dtexturefiltertype(filter), filter);
5749
5750     src_rect = *src_rect_in;
5751     dst_rect = *dst_rect_in;
5752
5753     switch (filter) {
5754         case WINED3DTEXF_LINEAR:
5755             gl_filter = GL_LINEAR;
5756             break;
5757
5758         default:
5759             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
5760         case WINED3DTEXF_NONE:
5761         case WINED3DTEXF_POINT:
5762             gl_filter = GL_NEAREST;
5763             break;
5764     }
5765
5766     /* Make sure the drawables are up-to-date. Note that loading the
5767      * destination surface isn't strictly required if we overwrite the
5768      * entire surface. */
5769     IWineD3DSurface_LoadLocation((IWineD3DSurface *)src_surface, SFLAG_INDRAWABLE, NULL);
5770     IWineD3DSurface_LoadLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, NULL);
5771
5772     if (!surface_is_offscreen(src_surface)) context = context_acquire(device, src_surface);
5773     else if (!surface_is_offscreen(dst_surface)) context = context_acquire(device, dst_surface);
5774     else context = context_acquire(device, NULL);
5775
5776     if (!context->valid)
5777     {
5778         context_release(context);
5779         WARN("Invalid context, skipping blit.\n");
5780         return;
5781     }
5782
5783     gl_info = context->gl_info;
5784
5785     if (!surface_is_offscreen(src_surface))
5786     {
5787         GLenum buffer = surface_get_gl_buffer(src_surface);
5788
5789         TRACE("Source surface %p is onscreen\n", src_surface);
5790
5791         if(buffer == GL_FRONT) {
5792             RECT windowsize;
5793             UINT h;
5794             ClientToScreen(context->win_handle, &offset);
5795             GetClientRect(context->win_handle, &windowsize);
5796             h = windowsize.bottom - windowsize.top;
5797             src_rect.left -= offset.x; src_rect.right -=offset.x;
5798             src_rect.top =  offset.y + h - src_rect.top;
5799             src_rect.bottom =  offset.y + h - src_rect.bottom;
5800         } else {
5801             src_rect.top = src_surface->currentDesc.Height - src_rect.top;
5802             src_rect.bottom = src_surface->currentDesc.Height - src_rect.bottom;
5803         }
5804
5805         ENTER_GL();
5806         context_bind_fbo(context, GL_READ_FRAMEBUFFER, NULL);
5807         glReadBuffer(buffer);
5808         checkGLcall("glReadBuffer()");
5809     } else {
5810         TRACE("Source surface %p is offscreen\n", src_surface);
5811         ENTER_GL();
5812         context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL);
5813         glReadBuffer(GL_COLOR_ATTACHMENT0);
5814         checkGLcall("glReadBuffer()");
5815     }
5816     LEAVE_GL();
5817
5818     /* Attach dst surface to dst fbo */
5819     if (!surface_is_offscreen(dst_surface))
5820     {
5821         GLenum buffer = surface_get_gl_buffer(dst_surface);
5822
5823         TRACE("Destination surface %p is onscreen\n", dst_surface);
5824
5825         if(buffer == GL_FRONT) {
5826             RECT windowsize;
5827             UINT h;
5828             ClientToScreen(context->win_handle, &offset);
5829             GetClientRect(context->win_handle, &windowsize);
5830             h = windowsize.bottom - windowsize.top;
5831             dst_rect.left -= offset.x; dst_rect.right -=offset.x;
5832             dst_rect.top =  offset.y + h - dst_rect.top;
5833             dst_rect.bottom =  offset.y + h - dst_rect.bottom;
5834         } else {
5835             /* Screen coords = window coords, surface height = window height */
5836             dst_rect.top = dst_surface->currentDesc.Height - dst_rect.top;
5837             dst_rect.bottom = dst_surface->currentDesc.Height - dst_rect.bottom;
5838         }
5839
5840         ENTER_GL();
5841         context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL);
5842         context_set_draw_buffer(context, buffer);
5843     }
5844     else
5845     {
5846         TRACE("Destination surface %p is offscreen\n", dst_surface);
5847
5848         ENTER_GL();
5849         context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL);
5850         context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0);
5851     }
5852     glDisable(GL_SCISSOR_TEST);
5853     IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5854
5855     gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
5856             dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, mask, gl_filter);
5857     checkGLcall("glBlitFramebuffer()");
5858
5859     LEAVE_GL();
5860
5861     if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
5862
5863     context_release(context);
5864
5865     IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, TRUE);
5866 }
5867
5868 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget,
5869                                                          BOOL set_viewport) {
5870     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5871
5872     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5873
5874     if (RenderTargetIndex >= This->adapter->gl_info.limits.buffers)
5875     {
5876         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
5877                 This, RenderTargetIndex, This->adapter->gl_info.limits.buffers);
5878         return WINED3DERR_INVALIDCALL;
5879     }
5880
5881     /* MSDN says that null disables the render target
5882     but a device must always be associated with a render target
5883     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5884     */
5885     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5886         FIXME("Trying to set render target 0 to NULL\n");
5887         return WINED3DERR_INVALIDCALL;
5888     }
5889     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5890         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);
5891         return WINED3DERR_INVALIDCALL;
5892     }
5893
5894     /* If we are trying to set what we already have, don't bother */
5895     if (pRenderTarget == (IWineD3DSurface *)This->render_targets[RenderTargetIndex])
5896     {
5897         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5898         return WINED3D_OK;
5899     }
5900     if (pRenderTarget)
5901         IWineD3DSurface_AddRef(pRenderTarget);
5902     if (This->render_targets[RenderTargetIndex])
5903         IWineD3DSurface_Release((IWineD3DSurface *)This->render_targets[RenderTargetIndex]);
5904     This->render_targets[RenderTargetIndex] = (IWineD3DSurfaceImpl *)pRenderTarget;
5905
5906     /* Render target 0 is special */
5907     if(RenderTargetIndex == 0 && set_viewport) {
5908         /* Finally, reset the viewport and scissor rect as the MSDN states.
5909          * Tests show that stateblock recording is ignored, the change goes
5910          * directly into the primary stateblock.
5911          */
5912         This->stateBlock->viewport.Height = This->render_targets[0]->currentDesc.Height;
5913         This->stateBlock->viewport.Width  = This->render_targets[0]->currentDesc.Width;
5914         This->stateBlock->viewport.X      = 0;
5915         This->stateBlock->viewport.Y      = 0;
5916         This->stateBlock->viewport.MaxZ   = 1.0f;
5917         This->stateBlock->viewport.MinZ   = 0.0f;
5918         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
5919
5920         This->stateBlock->scissorRect.top = 0;
5921         This->stateBlock->scissorRect.left = 0;
5922         This->stateBlock->scissorRect.right = This->stateBlock->viewport.Width;
5923         This->stateBlock->scissorRect.bottom = This->stateBlock->viewport.Height;
5924         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
5925     }
5926     return WINED3D_OK;
5927 }
5928
5929 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5930     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5931     IWineD3DSurfaceImpl *tmp;
5932
5933     TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This, pNewZStencil, This->depth_stencil);
5934
5935     if (This->depth_stencil == (IWineD3DSurfaceImpl *)pNewZStencil)
5936     {
5937         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5938         return WINED3D_OK;
5939     }
5940
5941     if (This->depth_stencil)
5942     {
5943         if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5944                 || This->depth_stencil->Flags & SFLAG_DISCARD)
5945         {
5946             surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED,
5947                     This->depth_stencil->currentDesc.Width,
5948                     This->depth_stencil->currentDesc.Height);
5949             if (This->depth_stencil == This->onscreen_depth_stencil)
5950             {
5951                 IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
5952                 This->onscreen_depth_stencil = NULL;
5953             }
5954         }
5955     }
5956
5957     tmp = This->depth_stencil;
5958     This->depth_stencil = (IWineD3DSurfaceImpl *)pNewZStencil;
5959     if (This->depth_stencil) IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil);
5960     if (tmp) IWineD3DSurface_Release((IWineD3DSurface *)tmp);
5961
5962     if ((!tmp && pNewZStencil) || (!pNewZStencil && tmp))
5963     {
5964         /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5965         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5966         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5967         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5968     }
5969
5970     return WINED3D_OK;
5971 }
5972
5973 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5974                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5975     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5976     /* TODO: the use of Impl is deprecated. */
5977     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5978     WINED3DLOCKED_RECT lockedRect;
5979
5980     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5981
5982     /* some basic validation checks */
5983     if (This->cursorTexture)
5984     {
5985         struct wined3d_context *context = context_acquire(This, NULL);
5986         ENTER_GL();
5987         glDeleteTextures(1, &This->cursorTexture);
5988         LEAVE_GL();
5989         context_release(context);
5990         This->cursorTexture = 0;
5991     }
5992
5993     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
5994         This->haveHardwareCursor = TRUE;
5995     else
5996         This->haveHardwareCursor = FALSE;
5997
5998     if(pCursorBitmap) {
5999         WINED3DLOCKED_RECT rect;
6000
6001         /* MSDN: Cursor must be A8R8G8B8 */
6002         if (pSur->resource.format_desc->format != WINED3DFMT_B8G8R8A8_UNORM)
6003         {
6004             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6005             return WINED3DERR_INVALIDCALL;
6006         }
6007
6008         /* MSDN: Cursor must be smaller than the display mode */
6009         if(pSur->currentDesc.Width > This->ddraw_width ||
6010            pSur->currentDesc.Height > This->ddraw_height) {
6011             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);
6012             return WINED3DERR_INVALIDCALL;
6013         }
6014
6015         if (!This->haveHardwareCursor) {
6016             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6017
6018             /* Do not store the surface's pointer because the application may
6019              * release it after setting the cursor image. Windows doesn't
6020              * addref the set surface, so we can't do this either without
6021              * creating circular refcount dependencies. Copy out the gl texture
6022              * instead.
6023              */
6024             This->cursorWidth = pSur->currentDesc.Width;
6025             This->cursorHeight = pSur->currentDesc.Height;
6026             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6027             {
6028                 const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
6029                 const struct wined3d_format_desc *format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, gl_info);
6030                 struct wined3d_context *context;
6031                 char *mem, *bits = rect.pBits;
6032                 GLint intfmt = format_desc->glInternal;
6033                 GLint format = format_desc->glFormat;
6034                 GLint type = format_desc->glType;
6035                 INT height = This->cursorHeight;
6036                 INT width = This->cursorWidth;
6037                 INT bpp = format_desc->byte_count;
6038                 DWORD sampler;
6039                 INT i;
6040
6041                 /* Reformat the texture memory (pitch and width can be
6042                  * different) */
6043                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6044                 for(i = 0; i < height; i++)
6045                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6046                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6047
6048                 context = context_acquire(This, NULL);
6049
6050                 ENTER_GL();
6051
6052                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
6053                 {
6054                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6055                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6056                 }
6057
6058                 /* Make sure that a proper texture unit is selected */
6059                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6060                 checkGLcall("glActiveTextureARB");
6061                 sampler = This->rev_tex_unit_map[0];
6062                 if (sampler != WINED3D_UNMAPPED_STAGE)
6063                 {
6064                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
6065                 }
6066                 /* Create a new cursor texture */
6067                 glGenTextures(1, &This->cursorTexture);
6068                 checkGLcall("glGenTextures");
6069                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6070                 checkGLcall("glBindTexture");
6071                 /* Copy the bitmap memory into the cursor texture */
6072                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6073                 HeapFree(GetProcessHeap(), 0, mem);
6074                 checkGLcall("glTexImage2D");
6075
6076                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
6077                 {
6078                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6079                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6080                 }
6081
6082                 LEAVE_GL();
6083
6084                 context_release(context);
6085             }
6086             else
6087             {
6088                 FIXME("A cursor texture was not returned.\n");
6089                 This->cursorTexture = 0;
6090             }
6091         }
6092         else
6093         {
6094             /* Draw a hardware cursor */
6095             ICONINFO cursorInfo;
6096             HCURSOR cursor;
6097             /* Create and clear maskBits because it is not needed for
6098              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6099              * chunks. */
6100             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6101                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6102             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6103                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6104                                          WINED3DLOCK_READONLY
6105             );
6106             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6107                   pSur->currentDesc.Height);
6108
6109             cursorInfo.fIcon = FALSE;
6110             cursorInfo.xHotspot = XHotSpot;
6111             cursorInfo.yHotspot = YHotSpot;
6112             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width, pSur->currentDesc.Height,
6113                     1, 1, maskBits);
6114             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width, pSur->currentDesc.Height,
6115                     1, 32, lockedRect.pBits);
6116             IWineD3DSurface_UnlockRect(pCursorBitmap);
6117             /* Create our cursor and clean up. */
6118             cursor = CreateIconIndirect(&cursorInfo);
6119             SetCursor(cursor);
6120             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6121             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6122             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6123             This->hardwareCursor = cursor;
6124             HeapFree(GetProcessHeap(), 0, maskBits);
6125         }
6126     }
6127
6128     This->xHotSpot = XHotSpot;
6129     This->yHotSpot = YHotSpot;
6130     return WINED3D_OK;
6131 }
6132
6133 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6134     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6135     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6136
6137     This->xScreenSpace = XScreenSpace;
6138     This->yScreenSpace = YScreenSpace;
6139
6140     return;
6141
6142 }
6143
6144 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6145     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6146     BOOL oldVisible = This->bCursorVisible;
6147     POINT pt;
6148
6149     TRACE("(%p) : visible(%d)\n", This, bShow);
6150
6151     /*
6152      * When ShowCursor is first called it should make the cursor appear at the OS's last
6153      * known cursor position.  Because of this, some applications just repetitively call
6154      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6155      */
6156     GetCursorPos(&pt);
6157     This->xScreenSpace = pt.x;
6158     This->yScreenSpace = pt.y;
6159
6160     if (This->haveHardwareCursor) {
6161         This->bCursorVisible = bShow;
6162         if (bShow)
6163             SetCursor(This->hardwareCursor);
6164         else
6165             SetCursor(NULL);
6166     }
6167     else
6168     {
6169         if (This->cursorTexture)
6170             This->bCursorVisible = bShow;
6171     }
6172
6173     return oldVisible;
6174 }
6175
6176 static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) {
6177     TRACE("checking resource %p for eviction\n", resource);
6178     if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) {
6179         TRACE("Evicting %p\n", resource);
6180         IWineD3DResource_UnLoad(resource);
6181     }
6182     IWineD3DResource_Release(resource);
6183     return S_OK;
6184 }
6185
6186 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice *iface)
6187 {
6188     TRACE("iface %p.\n", iface);
6189
6190     IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL);
6191     return WINED3D_OK;
6192 }
6193
6194 static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
6195 {
6196     IWineD3DDeviceImpl *device = surface->resource.device;
6197     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6198
6199     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6200     if(surface->Flags & SFLAG_DIBSECTION) {
6201         /* Release the DC */
6202         SelectObject(surface->hDC, surface->dib.holdbitmap);
6203         DeleteDC(surface->hDC);
6204         /* Release the DIB section */
6205         DeleteObject(surface->dib.DIBsection);
6206         surface->dib.bitmap_data = NULL;
6207         surface->resource.allocatedMemory = NULL;
6208         surface->Flags &= ~SFLAG_DIBSECTION;
6209     }
6210     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6211     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6212     if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
6213             || gl_info->supported[WINE_NORMALIZED_TEXRECT])
6214     {
6215         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6216         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6217     } else {
6218         surface->pow2Width = surface->pow2Height = 1;
6219         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6220         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6221     }
6222
6223     if (surface->texture_name)
6224     {
6225         struct wined3d_context *context = context_acquire(device, NULL);
6226         ENTER_GL();
6227         glDeleteTextures(1, &surface->texture_name);
6228         LEAVE_GL();
6229         context_release(context);
6230         surface->texture_name = 0;
6231         surface->Flags &= ~SFLAG_CLIENT;
6232     }
6233     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6234        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6235         surface->Flags |= SFLAG_NONPOW2;
6236     } else  {
6237         surface->Flags &= ~SFLAG_NONPOW2;
6238     }
6239     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
6240     surface->resource.allocatedMemory = NULL;
6241     surface->resource.heapMemory = NULL;
6242     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6243
6244     /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6245      * to a FBO */
6246     if (!surface_init_sysmem(surface))
6247     {
6248         return E_OUTOFMEMORY;
6249     }
6250     return WINED3D_OK;
6251 }
6252
6253 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6254     TRACE("Unloading resource %p\n", resource);
6255     IWineD3DResource_UnLoad(resource);
6256     IWineD3DResource_Release(resource);
6257     return S_OK;
6258 }
6259
6260 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
6261 {
6262     UINT i, count;
6263     WINED3DDISPLAYMODE m;
6264     HRESULT hr;
6265
6266     /* All Windowed modes are supported, as is leaving the current mode */
6267     if(pp->Windowed) return TRUE;
6268     if(!pp->BackBufferWidth) return TRUE;
6269     if(!pp->BackBufferHeight) return TRUE;
6270
6271     count = IWineD3D_GetAdapterModeCount(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN);
6272     for(i = 0; i < count; i++) {
6273         memset(&m, 0, sizeof(m));
6274         hr = IWineD3D_EnumAdapterModes(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN, i, &m);
6275         if(FAILED(hr)) {
6276             ERR("EnumAdapterModes failed\n");
6277         }
6278         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
6279             /* Mode found, it is supported */
6280             return TRUE;
6281         }
6282     }
6283     /* Mode not found -> not supported */
6284     return FALSE;
6285 }
6286
6287 static void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6288 {
6289     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6290     const struct wined3d_gl_info *gl_info;
6291     struct wined3d_context *context;
6292     IWineD3DBaseShaderImpl *shader;
6293
6294     context = context_acquire(This, NULL);
6295     gl_info = context->gl_info;
6296
6297     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6298     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6299         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6300     }
6301
6302     ENTER_GL();
6303     if(This->depth_blt_texture) {
6304         glDeleteTextures(1, &This->depth_blt_texture);
6305         This->depth_blt_texture = 0;
6306     }
6307     if (This->depth_blt_rb) {
6308         gl_info->fbo_ops.glDeleteRenderbuffers(1, &This->depth_blt_rb);
6309         This->depth_blt_rb = 0;
6310         This->depth_blt_rb_w = 0;
6311         This->depth_blt_rb_h = 0;
6312     }
6313     LEAVE_GL();
6314
6315     This->blitter->free_private(iface);
6316     This->frag_pipe->free_private(iface);
6317     This->shader_backend->shader_free_private(iface);
6318     destroy_dummy_textures(This, gl_info);
6319
6320     context_release(context);
6321
6322     while (This->numContexts)
6323     {
6324         context_destroy(This, This->contexts[0]);
6325     }
6326     HeapFree(GetProcessHeap(), 0, swapchain->context);
6327     swapchain->context = NULL;
6328     swapchain->num_contexts = 0;
6329 }
6330
6331 static HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6332 {
6333     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6334     struct wined3d_context *context;
6335     HRESULT hr;
6336     IWineD3DSurfaceImpl *target;
6337
6338     /* Recreate the primary swapchain's context */
6339     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
6340     if (!swapchain->context)
6341     {
6342         ERR("Failed to allocate memory for swapchain context array.\n");
6343         return E_OUTOFMEMORY;
6344     }
6345
6346     target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
6347     if (!(context = context_create(swapchain, target, swapchain->ds_format)))
6348     {
6349         WARN("Failed to create context.\n");
6350         HeapFree(GetProcessHeap(), 0, swapchain->context);
6351         return E_FAIL;
6352     }
6353
6354     swapchain->context[0] = context;
6355     swapchain->num_contexts = 1;
6356     create_dummy_textures(This);
6357     context_release(context);
6358
6359     hr = This->shader_backend->shader_alloc_private(iface);
6360     if (FAILED(hr))
6361     {
6362         ERR("Failed to allocate shader private data, hr %#x.\n", hr);
6363         goto err;
6364     }
6365
6366     hr = This->frag_pipe->alloc_private(iface);
6367     if (FAILED(hr))
6368     {
6369         ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr);
6370         This->shader_backend->shader_free_private(iface);
6371         goto err;
6372     }
6373
6374     hr = This->blitter->alloc_private(iface);
6375     if (FAILED(hr))
6376     {
6377         ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
6378         This->frag_pipe->free_private(iface);
6379         This->shader_backend->shader_free_private(iface);
6380         goto err;
6381     }
6382
6383     return WINED3D_OK;
6384
6385 err:
6386     context_acquire(This, NULL);
6387     destroy_dummy_textures(This, context->gl_info);
6388     context_release(context);
6389     context_destroy(This, context);
6390     HeapFree(GetProcessHeap(), 0, swapchain->context);
6391     swapchain->num_contexts = 0;
6392     return hr;
6393 }
6394
6395 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6396     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6397     IWineD3DSwapChainImpl *swapchain;
6398     HRESULT hr;
6399     BOOL DisplayModeChanged = FALSE;
6400     WINED3DDISPLAYMODE mode;
6401     TRACE("(%p)\n", This);
6402
6403     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6404     if(FAILED(hr)) {
6405         ERR("Failed to get the first implicit swapchain\n");
6406         return hr;
6407     }
6408
6409     if(!is_display_mode_supported(This, pPresentationParameters)) {
6410         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6411         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
6412              pPresentationParameters->BackBufferHeight);
6413         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6414         return WINED3DERR_INVALIDCALL;
6415     }
6416
6417     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6418      * on an existing gl context, so there's no real need for recreation.
6419      *
6420      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6421      *
6422      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6423      */
6424     TRACE("New params:\n");
6425     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6426     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6427     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6428     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6429     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6430     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6431     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6432     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6433     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6434     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6435     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6436     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6437     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6438
6439     /* No special treatment of these parameters. Just store them */
6440     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6441     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6442     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6443     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6444
6445     /* What to do about these? */
6446     if(pPresentationParameters->BackBufferCount != 0 &&
6447         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6448         ERR("Cannot change the back buffer count yet\n");
6449     }
6450     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6451         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6452         ERR("Cannot change the back buffer format yet\n");
6453     }
6454     if(pPresentationParameters->hDeviceWindow != NULL &&
6455         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6456         ERR("Cannot change the device window yet\n");
6457     }
6458     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil)
6459     {
6460         HRESULT hrc;
6461
6462         TRACE("Creating the depth stencil buffer\n");
6463
6464         hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
6465                 This->parent,
6466                 pPresentationParameters->BackBufferWidth,
6467                 pPresentationParameters->BackBufferHeight,
6468                 pPresentationParameters->AutoDepthStencilFormat,
6469                 pPresentationParameters->MultiSampleType,
6470                 pPresentationParameters->MultiSampleQuality,
6471                 FALSE,
6472                 (IWineD3DSurface **)&This->auto_depth_stencil);
6473
6474         if (FAILED(hrc)) {
6475             ERR("Failed to create the depth stencil buffer\n");
6476             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6477             return WINED3DERR_INVALIDCALL;
6478         }
6479     }
6480
6481     if (This->onscreen_depth_stencil)
6482     {
6483         IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
6484         This->onscreen_depth_stencil = NULL;
6485     }
6486
6487     /* Reset the depth stencil */
6488     if (pPresentationParameters->EnableAutoDepthStencil)
6489         IWineD3DDevice_SetDepthStencilSurface(iface, (IWineD3DSurface *)This->auto_depth_stencil);
6490     else
6491         IWineD3DDevice_SetDepthStencilSurface(iface, NULL);
6492
6493     TRACE("Resetting stateblock\n");
6494     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
6495     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
6496
6497     delete_opengl_contexts(iface, swapchain);
6498
6499     if(pPresentationParameters->Windowed) {
6500         mode.Width = swapchain->orig_width;
6501         mode.Height = swapchain->orig_height;
6502         mode.RefreshRate = 0;
6503         mode.Format = swapchain->presentParms.BackBufferFormat;
6504     } else {
6505         mode.Width = pPresentationParameters->BackBufferWidth;
6506         mode.Height = pPresentationParameters->BackBufferHeight;
6507         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6508         mode.Format = swapchain->presentParms.BackBufferFormat;
6509     }
6510
6511     /* Should Width == 800 && Height == 0 set 800x600? */
6512     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6513        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6514         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6515     {
6516         UINT i;
6517
6518         if(!pPresentationParameters->Windowed) {
6519             DisplayModeChanged = TRUE;
6520         }
6521         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6522         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6523
6524         hr = updateSurfaceDesc(swapchain->front_buffer, pPresentationParameters);
6525         if(FAILED(hr))
6526         {
6527             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6528             return hr;
6529         }
6530
6531         for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i)
6532         {
6533             hr = updateSurfaceDesc(swapchain->back_buffers[i], pPresentationParameters);
6534             if(FAILED(hr))
6535             {
6536                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6537                 return hr;
6538             }
6539         }
6540         if (This->auto_depth_stencil)
6541         {
6542             hr = updateSurfaceDesc(This->auto_depth_stencil, pPresentationParameters);
6543             if(FAILED(hr))
6544             {
6545                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6546                 return hr;
6547             }
6548         }
6549     }
6550
6551     if (!pPresentationParameters->Windowed != !swapchain->presentParms.Windowed
6552             || DisplayModeChanged)
6553     {
6554         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6555
6556         if (!pPresentationParameters->Windowed)
6557         {
6558             if(swapchain->presentParms.Windowed) {
6559                 /* switch from windowed to fs */
6560                 swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6561                         pPresentationParameters->BackBufferHeight);
6562             } else {
6563                 /* Fullscreen -> fullscreen mode change */
6564                 MoveWindow(swapchain->device_window, 0, 0,
6565                            pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
6566                            TRUE);
6567             }
6568         }
6569         else if (!swapchain->presentParms.Windowed)
6570         {
6571             /* Fullscreen -> windowed switch */
6572             swapchain_restore_fullscreen_window(swapchain);
6573         }
6574         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6575     } else if(!pPresentationParameters->Windowed) {
6576         DWORD style = This->style, exStyle = This->exStyle;
6577         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6578          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6579          * Reset to clear up their mess. Guild Wars also loses the device during that.
6580          */
6581         This->style = 0;
6582         This->exStyle = 0;
6583         swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6584                 pPresentationParameters->BackBufferHeight);
6585         This->style = style;
6586         This->exStyle = exStyle;
6587     }
6588
6589     /* Note: No parent needed for initial internal stateblock */
6590     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock, NULL);
6591     if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6592     else TRACE("Created stateblock %p\n", This->stateBlock);
6593     This->updateStateBlock = This->stateBlock;
6594     IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
6595
6596     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
6597     if(FAILED(hr)) {
6598         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6599     }
6600
6601     if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
6602     {
6603         RECT client_rect;
6604         GetClientRect(swapchain->win_handle, &client_rect);
6605
6606         if(!swapchain->presentParms.BackBufferCount)
6607         {
6608             TRACE("Single buffered rendering\n");
6609             swapchain->render_to_fbo = FALSE;
6610         }
6611         else if(swapchain->presentParms.BackBufferWidth  != client_rect.right  ||
6612                 swapchain->presentParms.BackBufferHeight != client_rect.bottom )
6613         {
6614             TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6615                     swapchain->presentParms.BackBufferWidth,
6616                     swapchain->presentParms.BackBufferHeight,
6617                     client_rect.right, client_rect.bottom);
6618             swapchain->render_to_fbo = TRUE;
6619         }
6620         else
6621         {
6622             TRACE("Rendering directly to GL_BACK\n");
6623             swapchain->render_to_fbo = FALSE;
6624         }
6625     }
6626
6627     hr = create_primary_opengl_context(iface, swapchain);
6628     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6629
6630     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6631      * first use
6632      */
6633     return hr;
6634 }
6635
6636 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL enable_dialogs)
6637 {
6638     TRACE("iface %p, enable_dialogs %#x.\n", iface, enable_dialogs);
6639
6640     if (!enable_dialogs) FIXME("Dialogs cannot be disabled yet.\n");
6641
6642     return WINED3D_OK;
6643 }
6644
6645
6646 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6647     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6648     TRACE("(%p) : pParameters %p\n", This, pParameters);
6649
6650     *pParameters = This->createParms;
6651     return WINED3D_OK;
6652 }
6653
6654 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6655     IWineD3DSwapChain *swapchain;
6656
6657     TRACE("Relaying  to swapchain\n");
6658
6659     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6660         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, pRamp);
6661         IWineD3DSwapChain_Release(swapchain);
6662     }
6663 }
6664
6665 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6666     IWineD3DSwapChain *swapchain;
6667
6668     TRACE("Relaying  to swapchain\n");
6669
6670     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6671         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6672         IWineD3DSwapChain_Release(swapchain);
6673     }
6674 }
6675
6676
6677 /** ********************************************************
6678 *   Notification functions
6679 ** ********************************************************/
6680 /** This function must be called in the release of a resource when ref == 0,
6681 * the contents of resource must still be correct,
6682 * any handles to other resource held by the caller must be closed
6683 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6684  *****************************************************/
6685 void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6686 {
6687     TRACE("(%p) : Adding resource %p\n", This, resource);
6688
6689     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6690 }
6691
6692 static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6693 {
6694     TRACE("(%p) : Removing resource %p\n", This, resource);
6695
6696     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6697 }
6698
6699 void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6700 {
6701     WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource);
6702     int counter;
6703
6704     TRACE("(%p) : resource %p\n", This, resource);
6705
6706     context_resource_released((IWineD3DDevice *)This, resource, type);
6707
6708     switch (type) {
6709         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6710         case WINED3DRTYPE_SURFACE: {
6711             unsigned int i;
6712
6713             if (This->d3d_initialized)
6714             {
6715                 for (i = 0; i < This->adapter->gl_info.limits.buffers; ++i)
6716                 {
6717                     if (This->render_targets[i] == (IWineD3DSurfaceImpl *)resource)
6718                         This->render_targets[i] = NULL;
6719                 }
6720                 if (This->depth_stencil == (IWineD3DSurfaceImpl *)resource)
6721                     This->depth_stencil = NULL;
6722             }
6723
6724             break;
6725         }
6726         case WINED3DRTYPE_TEXTURE:
6727         case WINED3DRTYPE_CUBETEXTURE:
6728         case WINED3DRTYPE_VOLUMETEXTURE:
6729                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
6730                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6731                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6732                         This->stateBlock->textures[counter] = NULL;
6733                     }
6734                     if (This->updateStateBlock != This->stateBlock ){
6735                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6736                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6737                             This->updateStateBlock->textures[counter] = NULL;
6738                         }
6739                     }
6740                 }
6741         break;
6742         case WINED3DRTYPE_VOLUME:
6743         /* TODO: nothing really? */
6744         break;
6745         case WINED3DRTYPE_BUFFER:
6746         {
6747             int streamNumber;
6748             TRACE("Cleaning up stream pointers\n");
6749
6750             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6751                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6752                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6753                 */
6754                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6755                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6756                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6757                         This->updateStateBlock->streamSource[streamNumber] = 0;
6758                         /* Set changed flag? */
6759                     }
6760                 }
6761                 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) */
6762                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6763                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6764                         This->stateBlock->streamSource[streamNumber] = 0;
6765                     }
6766                 }
6767             }
6768
6769             if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6770                 if (This->updateStateBlock->pIndexData == (IWineD3DBuffer *)resource) {
6771                     This->updateStateBlock->pIndexData =  NULL;
6772                 }
6773             }
6774             if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6775                 if (This->stateBlock->pIndexData == (IWineD3DBuffer *)resource) {
6776                     This->stateBlock->pIndexData =  NULL;
6777                 }
6778             }
6779         }
6780         break;
6781
6782         default:
6783         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6784         break;
6785     }
6786
6787
6788     /* Remove the resource from the resourceStore */
6789     device_resource_remove(This, resource);
6790
6791     TRACE("Resource released\n");
6792
6793 }
6794
6795 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
6796     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6797     IWineD3DResourceImpl *resource, *cursor;
6798     HRESULT ret;
6799     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
6800
6801     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6802         TRACE("enumerating resource %p\n", resource);
6803         IWineD3DResource_AddRef((IWineD3DResource *) resource);
6804         ret = pCallback((IWineD3DResource *) resource, pData);
6805         if(ret == S_FALSE) {
6806             TRACE("Canceling enumeration\n");
6807             break;
6808         }
6809     }
6810     return WINED3D_OK;
6811 }
6812
6813 static HRESULT WINAPI IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice *iface, HDC dc, IWineD3DSurface **surface)
6814 {
6815     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6816     IWineD3DResourceImpl *resource;
6817
6818     LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry)
6819     {
6820         WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource);
6821         if (type == WINED3DRTYPE_SURFACE)
6822         {
6823             if (((IWineD3DSurfaceImpl *)resource)->hDC == dc)
6824             {
6825                 TRACE("Found surface %p for dc %p.\n", resource, dc);
6826                 *surface = (IWineD3DSurface *)resource;
6827                 return WINED3D_OK;
6828             }
6829         }
6830     }
6831
6832     return WINED3DERR_INVALIDCALL;
6833 }
6834
6835 /**********************************************************
6836  * IWineD3DDevice VTbl follows
6837  **********************************************************/
6838
6839 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6840 {
6841     /*** IUnknown methods ***/
6842     IWineD3DDeviceImpl_QueryInterface,
6843     IWineD3DDeviceImpl_AddRef,
6844     IWineD3DDeviceImpl_Release,
6845     /*** IWineD3DDevice methods ***/
6846     IWineD3DDeviceImpl_GetParent,
6847     /*** Creation methods**/
6848     IWineD3DDeviceImpl_CreateBuffer,
6849     IWineD3DDeviceImpl_CreateVertexBuffer,
6850     IWineD3DDeviceImpl_CreateIndexBuffer,
6851     IWineD3DDeviceImpl_CreateStateBlock,
6852     IWineD3DDeviceImpl_CreateSurface,
6853     IWineD3DDeviceImpl_CreateRendertargetView,
6854     IWineD3DDeviceImpl_CreateTexture,
6855     IWineD3DDeviceImpl_CreateVolumeTexture,
6856     IWineD3DDeviceImpl_CreateVolume,
6857     IWineD3DDeviceImpl_CreateCubeTexture,
6858     IWineD3DDeviceImpl_CreateQuery,
6859     IWineD3DDeviceImpl_CreateSwapChain,
6860     IWineD3DDeviceImpl_CreateVertexDeclaration,
6861     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
6862     IWineD3DDeviceImpl_CreateVertexShader,
6863     IWineD3DDeviceImpl_CreateGeometryShader,
6864     IWineD3DDeviceImpl_CreatePixelShader,
6865     IWineD3DDeviceImpl_CreatePalette,
6866     /*** Odd functions **/
6867     IWineD3DDeviceImpl_Init3D,
6868     IWineD3DDeviceImpl_InitGDI,
6869     IWineD3DDeviceImpl_Uninit3D,
6870     IWineD3DDeviceImpl_UninitGDI,
6871     IWineD3DDeviceImpl_SetMultithreaded,
6872     IWineD3DDeviceImpl_EvictManagedResources,
6873     IWineD3DDeviceImpl_GetAvailableTextureMem,
6874     IWineD3DDeviceImpl_GetBackBuffer,
6875     IWineD3DDeviceImpl_GetCreationParameters,
6876     IWineD3DDeviceImpl_GetDeviceCaps,
6877     IWineD3DDeviceImpl_GetDirect3D,
6878     IWineD3DDeviceImpl_GetDisplayMode,
6879     IWineD3DDeviceImpl_SetDisplayMode,
6880     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6881     IWineD3DDeviceImpl_GetRasterStatus,
6882     IWineD3DDeviceImpl_GetSwapChain,
6883     IWineD3DDeviceImpl_Reset,
6884     IWineD3DDeviceImpl_SetDialogBoxMode,
6885     IWineD3DDeviceImpl_SetCursorProperties,
6886     IWineD3DDeviceImpl_SetCursorPosition,
6887     IWineD3DDeviceImpl_ShowCursor,
6888     /*** Getters and setters **/
6889     IWineD3DDeviceImpl_SetClipPlane,
6890     IWineD3DDeviceImpl_GetClipPlane,
6891     IWineD3DDeviceImpl_SetClipStatus,
6892     IWineD3DDeviceImpl_GetClipStatus,
6893     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6894     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6895     IWineD3DDeviceImpl_SetDepthStencilSurface,
6896     IWineD3DDeviceImpl_GetDepthStencilSurface,
6897     IWineD3DDeviceImpl_SetGammaRamp,
6898     IWineD3DDeviceImpl_GetGammaRamp,
6899     IWineD3DDeviceImpl_SetIndexBuffer,
6900     IWineD3DDeviceImpl_GetIndexBuffer,
6901     IWineD3DDeviceImpl_SetBaseVertexIndex,
6902     IWineD3DDeviceImpl_GetBaseVertexIndex,
6903     IWineD3DDeviceImpl_SetLight,
6904     IWineD3DDeviceImpl_GetLight,
6905     IWineD3DDeviceImpl_SetLightEnable,
6906     IWineD3DDeviceImpl_GetLightEnable,
6907     IWineD3DDeviceImpl_SetMaterial,
6908     IWineD3DDeviceImpl_GetMaterial,
6909     IWineD3DDeviceImpl_SetNPatchMode,
6910     IWineD3DDeviceImpl_GetNPatchMode,
6911     IWineD3DDeviceImpl_SetPaletteEntries,
6912     IWineD3DDeviceImpl_GetPaletteEntries,
6913     IWineD3DDeviceImpl_SetPixelShader,
6914     IWineD3DDeviceImpl_GetPixelShader,
6915     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6916     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6917     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6918     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6919     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6920     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6921     IWineD3DDeviceImpl_SetRenderState,
6922     IWineD3DDeviceImpl_GetRenderState,
6923     IWineD3DDeviceImpl_SetRenderTarget,
6924     IWineD3DDeviceImpl_GetRenderTarget,
6925     IWineD3DDeviceImpl_SetFrontBackBuffers,
6926     IWineD3DDeviceImpl_SetSamplerState,
6927     IWineD3DDeviceImpl_GetSamplerState,
6928     IWineD3DDeviceImpl_SetScissorRect,
6929     IWineD3DDeviceImpl_GetScissorRect,
6930     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6931     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6932     IWineD3DDeviceImpl_SetStreamSource,
6933     IWineD3DDeviceImpl_GetStreamSource,
6934     IWineD3DDeviceImpl_SetStreamSourceFreq,
6935     IWineD3DDeviceImpl_GetStreamSourceFreq,
6936     IWineD3DDeviceImpl_SetTexture,
6937     IWineD3DDeviceImpl_GetTexture,
6938     IWineD3DDeviceImpl_SetTextureStageState,
6939     IWineD3DDeviceImpl_GetTextureStageState,
6940     IWineD3DDeviceImpl_SetTransform,
6941     IWineD3DDeviceImpl_GetTransform,
6942     IWineD3DDeviceImpl_SetVertexDeclaration,
6943     IWineD3DDeviceImpl_GetVertexDeclaration,
6944     IWineD3DDeviceImpl_SetVertexShader,
6945     IWineD3DDeviceImpl_GetVertexShader,
6946     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6947     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6948     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6949     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6950     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6951     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6952     IWineD3DDeviceImpl_SetViewport,
6953     IWineD3DDeviceImpl_GetViewport,
6954     IWineD3DDeviceImpl_MultiplyTransform,
6955     IWineD3DDeviceImpl_ValidateDevice,
6956     IWineD3DDeviceImpl_ProcessVertices,
6957     /*** State block ***/
6958     IWineD3DDeviceImpl_BeginStateBlock,
6959     IWineD3DDeviceImpl_EndStateBlock,
6960     /*** Scene management ***/
6961     IWineD3DDeviceImpl_BeginScene,
6962     IWineD3DDeviceImpl_EndScene,
6963     IWineD3DDeviceImpl_Present,
6964     IWineD3DDeviceImpl_Clear,
6965     IWineD3DDeviceImpl_ClearRendertargetView,
6966     /*** Drawing ***/
6967     IWineD3DDeviceImpl_SetPrimitiveType,
6968     IWineD3DDeviceImpl_GetPrimitiveType,
6969     IWineD3DDeviceImpl_DrawPrimitive,
6970     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6971     IWineD3DDeviceImpl_DrawPrimitiveUP,
6972     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6973     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6974     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
6975     IWineD3DDeviceImpl_DrawRectPatch,
6976     IWineD3DDeviceImpl_DrawTriPatch,
6977     IWineD3DDeviceImpl_DeletePatch,
6978     IWineD3DDeviceImpl_ColorFill,
6979     IWineD3DDeviceImpl_UpdateTexture,
6980     IWineD3DDeviceImpl_UpdateSurface,
6981     IWineD3DDeviceImpl_GetFrontBufferData,
6982     /*** object tracking ***/
6983     IWineD3DDeviceImpl_EnumResources,
6984     IWineD3DDeviceImpl_GetSurfaceFromDC,
6985     IWineD3DDeviceImpl_AcquireFocusWindow,
6986     IWineD3DDeviceImpl_ReleaseFocusWindow,
6987 };
6988
6989 HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d,
6990         UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags,
6991         IUnknown *parent, IWineD3DDeviceParent *device_parent)
6992 {
6993     struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
6994     const struct fragment_pipeline *fragment_pipeline;
6995     struct shader_caps shader_caps;
6996     struct fragment_caps ffp_caps;
6997     WINED3DDISPLAYMODE mode;
6998     unsigned int i;
6999     HRESULT hr;
7000
7001     device->lpVtbl = &IWineD3DDevice_Vtbl;
7002     device->ref = 1;
7003     device->wined3d = (IWineD3D *)wined3d;
7004     IWineD3D_AddRef(device->wined3d);
7005     device->adapter = wined3d->adapter_count ? adapter : NULL;
7006     device->parent  = parent;
7007     device->device_parent = device_parent;
7008     list_init(&device->resources);
7009     list_init(&device->shaders);
7010
7011     device->surface_alignment = wined3d->dxVersion == 7 ? DDRAW_PITCH_ALIGNMENT : D3D8_PITCH_ALIGNMENT;
7012     device->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
7013
7014     /* Get the initial screen setup for ddraw. */
7015     hr = IWineD3D_GetAdapterDisplayMode((IWineD3D *)wined3d, adapter_idx, &mode);
7016     if (FAILED(hr))
7017     {
7018         ERR("Failed to get the adapter's display mode, hr %#x.\n", hr);
7019         IWineD3D_Release(device->wined3d);
7020         return hr;
7021     }
7022     device->ddraw_width = mode.Width;
7023     device->ddraw_height = mode.Height;
7024     device->ddraw_format = mode.Format;
7025
7026     /* Save the creation parameters. */
7027     device->createParms.AdapterOrdinal = adapter_idx;
7028     device->createParms.DeviceType = device_type;
7029     device->createParms.hFocusWindow = focus_window;
7030     device->createParms.BehaviorFlags = flags;
7031
7032     device->devType = device_type;
7033     for (i = 0; i < PATCHMAP_SIZE; ++i) list_init(&device->patches[i]);
7034
7035     select_shader_mode(&adapter->gl_info, &device->ps_selected_mode, &device->vs_selected_mode);
7036     device->shader_backend = adapter->shader_backend;
7037
7038     if (device->shader_backend)
7039     {
7040         device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
7041         device->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
7042         device->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
7043         device->vs_clipping = shader_caps.VSClipping;
7044     }
7045     fragment_pipeline = adapter->fragment_pipe;
7046     device->frag_pipe = fragment_pipeline;
7047     if (fragment_pipeline)
7048     {
7049         fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
7050         device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
7051
7052         hr = compile_state_table(device->StateTable, device->multistate_funcs, &adapter->gl_info,
7053                                  ffp_vertexstate_template, fragment_pipeline, misc_state_template);
7054         if (FAILED(hr))
7055         {
7056             ERR("Failed to compile state table, hr %#x.\n", hr);
7057             IWineD3D_Release(device->wined3d);
7058             return hr;
7059         }
7060     }
7061     device->blitter = adapter->blitter;
7062
7063     return WINED3D_OK;
7064 }
7065
7066
7067 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7068     DWORD rep = This->StateTable[state].representative;
7069     struct wined3d_context *context;
7070     DWORD idx;
7071     BYTE shift;
7072     UINT i;
7073
7074     for(i = 0; i < This->numContexts; i++) {
7075         context = This->contexts[i];
7076         if(isStateDirty(context, rep)) continue;
7077
7078         context->dirtyArray[context->numDirtyEntries++] = rep;
7079         idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
7080         shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
7081         context->isStateDirty[idx] |= (1 << shift);
7082     }
7083 }
7084
7085 void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height)
7086 {
7087     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
7088     *width = context->current_rt->pow2Width;
7089     *height = context->current_rt->pow2Height;
7090 }
7091
7092 void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height)
7093 {
7094     IWineD3DSwapChainImpl *swapchain = context->swapchain;
7095     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7096      * current context's drawable, which is the size of the back buffer of the swapchain
7097      * the active context belongs to. */
7098     *width = swapchain->presentParms.BackBufferWidth;
7099     *height = swapchain->presentParms.BackBufferHeight;
7100 }
7101
7102 LRESULT device_process_message(IWineD3DDeviceImpl *device, HWND window,
7103         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
7104 {
7105     if (device->filter_messages)
7106     {
7107         TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
7108                 window, message, wparam, lparam);
7109         return DefWindowProcW(window, message, wparam, lparam);
7110     }
7111
7112     if (message == WM_DESTROY)
7113     {
7114         TRACE("unregister window %p.\n", window);
7115         wined3d_unregister_window(window);
7116
7117         if (device->focus_window == window) device->focus_window = NULL;
7118         else ERR("Window %p is not the focus window for device %p.\n", window, device);
7119     }
7120
7121     return CallWindowProcW(proc, window, message, wparam, lparam);
7122 }