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