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