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