wined3d: Move sampler states 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->state.sampler_states[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->state.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->state.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->state.transforms[d3dts].u.m[0][0], lpmatrix, sizeof(*lpmatrix)))
2429     {
2430         TRACE("The app is setting the same matrix over again\n");
2431         return WINED3D_OK;
2432     }
2433     else
2434     {
2435         conv_mat(lpmatrix, &This->stateBlock->state.transforms[d3dts].u.m[0][0]);
2436     }
2437
2438     /*
2439        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2440        where ViewMat = Camera space, WorldMat = world space.
2441
2442        In OpenGL, camera and world space is combined into GL_MODELVIEW
2443        matrix.  The Projection matrix stay projection matrix.
2444      */
2445
2446     /* Capture the times we can just ignore the change for now */
2447     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrix */
2448         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2449         /* Handled by the state manager */
2450     }
2451
2452     if (d3dts < WINED3DTS_WORLDMATRIX(This->adapter->gl_info.limits.blends))
2453         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2454
2455     return WINED3D_OK;
2456
2457 }
2458
2459 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface,
2460         WINED3DTRANSFORMSTATETYPE state, WINED3DMATRIX *matrix)
2461 {
2462     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
2463
2464     TRACE("iface %p, state %s, matrix %p.\n", iface, debug_d3dtstype(state), matrix);
2465
2466     *matrix = device->stateBlock->state.transforms[state];
2467
2468     return WINED3D_OK;
2469 }
2470
2471 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2472     const WINED3DMATRIX *mat = NULL;
2473     WINED3DMATRIX temp;
2474
2475     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2476      * below means it will be recorded in a state block change, but it
2477      * works regardless where it is recorded.
2478      * If this is found to be wrong, change to StateBlock.
2479      */
2480     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2481     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2482
2483     if (State <= HIGHEST_TRANSFORMSTATE)
2484     {
2485         mat = &This->updateStateBlock->state.transforms[State];
2486     }
2487     else
2488     {
2489         FIXME("Unhandled transform state!!\n");
2490     }
2491
2492     multiply_matrix(&temp, mat, pMatrix);
2493
2494     /* Apply change via set transform - will reapply to eg. lights this way */
2495     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2496 }
2497
2498 /*****
2499  * Get / Set Light
2500  *****/
2501 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2502    you can reference any indexes you want as long as that number max are enabled at any
2503    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2504    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2505    but when recording, just build a chain pretty much of commands to be replayed.                  */
2506
2507 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2508     float rho;
2509     struct wined3d_light_info *object = NULL;
2510     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2511     struct list *e;
2512
2513     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2514     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2515
2516     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2517      * the gl driver.
2518      */
2519     if(!pLight) {
2520         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2521         return WINED3DERR_INVALIDCALL;
2522     }
2523
2524     switch(pLight->Type) {
2525         case WINED3DLIGHT_POINT:
2526         case WINED3DLIGHT_SPOT:
2527         case WINED3DLIGHT_PARALLELPOINT:
2528         case WINED3DLIGHT_GLSPOT:
2529             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2530              * most wanted
2531              */
2532             if (pLight->Attenuation0 < 0.0f || pLight->Attenuation1 < 0.0f || pLight->Attenuation2 < 0.0f)
2533             {
2534                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2535                 return WINED3DERR_INVALIDCALL;
2536             }
2537             break;
2538
2539         case WINED3DLIGHT_DIRECTIONAL:
2540             /* Ignores attenuation */
2541             break;
2542
2543         default:
2544         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2545         return WINED3DERR_INVALIDCALL;
2546     }
2547
2548     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi])
2549     {
2550         object = LIST_ENTRY(e, struct wined3d_light_info, entry);
2551         if(object->OriginalIndex == Index) break;
2552         object = NULL;
2553     }
2554
2555     if(!object) {
2556         TRACE("Adding new light\n");
2557         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2558         if(!object) {
2559             ERR("Out of memory error when allocating a light\n");
2560             return E_OUTOFMEMORY;
2561         }
2562         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2563         object->glIndex = -1;
2564         object->OriginalIndex = Index;
2565     }
2566
2567     /* Initialize the object */
2568     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,
2569           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2570           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2571           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2572     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2573           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2574     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2575
2576     /* Save away the information */
2577     object->OriginalParms = *pLight;
2578
2579     switch (pLight->Type) {
2580     case WINED3DLIGHT_POINT:
2581         /* Position */
2582         object->lightPosn[0] = pLight->Position.x;
2583         object->lightPosn[1] = pLight->Position.y;
2584         object->lightPosn[2] = pLight->Position.z;
2585         object->lightPosn[3] = 1.0f;
2586         object->cutoff = 180.0f;
2587         /* FIXME: Range */
2588         break;
2589
2590     case WINED3DLIGHT_DIRECTIONAL:
2591         /* Direction */
2592         object->lightPosn[0] = -pLight->Direction.x;
2593         object->lightPosn[1] = -pLight->Direction.y;
2594         object->lightPosn[2] = -pLight->Direction.z;
2595         object->lightPosn[3] = 0.0f;
2596         object->exponent     = 0.0f;
2597         object->cutoff       = 180.0f;
2598         break;
2599
2600     case WINED3DLIGHT_SPOT:
2601         /* Position */
2602         object->lightPosn[0] = pLight->Position.x;
2603         object->lightPosn[1] = pLight->Position.y;
2604         object->lightPosn[2] = pLight->Position.z;
2605         object->lightPosn[3] = 1.0f;
2606
2607         /* Direction */
2608         object->lightDirn[0] = pLight->Direction.x;
2609         object->lightDirn[1] = pLight->Direction.y;
2610         object->lightDirn[2] = pLight->Direction.z;
2611         object->lightDirn[3] = 1.0f;
2612
2613         /*
2614          * opengl-ish and d3d-ish spot lights use too different models for the
2615          * light "intensity" as a function of the angle towards the main light direction,
2616          * so we only can approximate very roughly.
2617          * however spot lights are rather rarely used in games (if ever used at all).
2618          * furthermore if still used, probably nobody pays attention to such details.
2619          */
2620         if (!pLight->Falloff)
2621         {
2622             /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2623              * falloff resp. exponent parameter as an exponent, so the spot light lighting
2624              * will always be 1.0 for both of them, and we don't have to care for the
2625              * rest of the rather complex calculation
2626              */
2627             object->exponent = 0.0f;
2628         } else {
2629             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2630             if (rho < 0.0001f) rho = 0.0001f;
2631             object->exponent = -0.3f/logf(cosf(rho/2));
2632         }
2633         if (object->exponent > 128.0f)
2634         {
2635             object->exponent = 128.0f;
2636         }
2637         object->cutoff = (float) (pLight->Phi*90/M_PI);
2638
2639         /* FIXME: Range */
2640         break;
2641
2642     default:
2643         FIXME("Unrecognized light type %d\n", pLight->Type);
2644     }
2645
2646     /* Update the live definitions if the light is currently assigned a glIndex */
2647     if (object->glIndex != -1 && !This->isRecordingState) {
2648         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2649     }
2650     return WINED3D_OK;
2651 }
2652
2653 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT *pLight)
2654 {
2655     struct wined3d_light_info *lightInfo = NULL;
2656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2657     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2658     struct list *e;
2659     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2660
2661     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi])
2662     {
2663         lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2664         if(lightInfo->OriginalIndex == Index) break;
2665         lightInfo = NULL;
2666     }
2667
2668     if (!lightInfo)
2669     {
2670         TRACE("Light information requested but light not defined\n");
2671         return WINED3DERR_INVALIDCALL;
2672     }
2673
2674     *pLight = lightInfo->OriginalParms;
2675     return WINED3D_OK;
2676 }
2677
2678 /*****
2679  * Get / Set Light Enable
2680  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2681  *****/
2682 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable)
2683 {
2684     struct wined3d_light_info *lightInfo = NULL;
2685     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2686     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2687     struct list *e;
2688     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2689
2690     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi])
2691     {
2692         lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2693         if(lightInfo->OriginalIndex == Index) break;
2694         lightInfo = NULL;
2695     }
2696     TRACE("Found light: %p\n", lightInfo);
2697
2698     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2699     if (!lightInfo)
2700     {
2701         TRACE("Light enabled requested but light not defined, so defining one!\n");
2702         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2703
2704         /* Search for it again! Should be fairly quick as near head of list */
2705         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi])
2706         {
2707             lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2708             if(lightInfo->OriginalIndex == Index) break;
2709             lightInfo = NULL;
2710         }
2711         if (!lightInfo)
2712         {
2713             FIXME("Adding default lights has failed dismally\n");
2714             return WINED3DERR_INVALIDCALL;
2715         }
2716     }
2717
2718     if(!Enable) {
2719         if(lightInfo->glIndex != -1) {
2720             if(!This->isRecordingState) {
2721                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2722             }
2723
2724             This->updateStateBlock->activeLights[lightInfo->glIndex] = NULL;
2725             lightInfo->glIndex = -1;
2726         } else {
2727             TRACE("Light already disabled, nothing to do\n");
2728         }
2729         lightInfo->enabled = FALSE;
2730     } else {
2731         lightInfo->enabled = TRUE;
2732         if (lightInfo->glIndex != -1) {
2733             /* nop */
2734             TRACE("Nothing to do as light was enabled\n");
2735         } else {
2736             int i;
2737             /* Find a free gl light */
2738             for (i = 0; i < This->maxConcurrentLights; ++i)
2739             {
2740                 if (!This->updateStateBlock->activeLights[i])
2741                 {
2742                     This->updateStateBlock->activeLights[i] = lightInfo;
2743                     lightInfo->glIndex = i;
2744                     break;
2745                 }
2746             }
2747             if(lightInfo->glIndex == -1) {
2748                 /* Our tests show that Windows returns D3D_OK in this situation, even with
2749                  * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2750                  * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2751                  * as well for those lights.
2752                  *
2753                  * TODO: Test how this affects rendering
2754                  */
2755                 WARN("Too many concurrently active lights\n");
2756                 return WINED3D_OK;
2757             }
2758
2759             /* i == lightInfo->glIndex */
2760             if(!This->isRecordingState) {
2761                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2762             }
2763         }
2764     }
2765
2766     return WINED3D_OK;
2767 }
2768
2769 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable)
2770 {
2771     struct wined3d_light_info *lightInfo = NULL;
2772     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2773     struct list *e;
2774     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2775     TRACE("(%p) : for idx(%d)\n", This, Index);
2776
2777     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi])
2778     {
2779         lightInfo = LIST_ENTRY(e, struct wined3d_light_info, entry);
2780         if(lightInfo->OriginalIndex == Index) break;
2781         lightInfo = NULL;
2782     }
2783
2784     if (!lightInfo)
2785     {
2786         TRACE("Light enabled state requested but light not defined\n");
2787         return WINED3DERR_INVALIDCALL;
2788     }
2789     /* true is 128 according to SetLightEnable */
2790     *pEnable = lightInfo->enabled ? 128 : 0;
2791     return WINED3D_OK;
2792 }
2793
2794 /*****
2795  * Get / Set Clip Planes
2796  *****/
2797 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2798     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2799     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2800
2801     /* Validate Index */
2802     if (Index >= This->adapter->gl_info.limits.clipplanes)
2803     {
2804         TRACE("Application has requested clipplane this device doesn't support\n");
2805         return WINED3DERR_INVALIDCALL;
2806     }
2807
2808     This->updateStateBlock->changed.clipplane |= 1 << Index;
2809
2810     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2811        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2812        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2813        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2814         TRACE("Application is setting old values over, nothing to do\n");
2815         return WINED3D_OK;
2816     }
2817
2818     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2819     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2820     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2821     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2822
2823     /* Handle recording of state blocks */
2824     if (This->isRecordingState) {
2825         TRACE("Recording... not performing anything\n");
2826         return WINED3D_OK;
2827     }
2828
2829     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2830
2831     return WINED3D_OK;
2832 }
2833
2834 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2835     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2836     TRACE("(%p) : for idx %d\n", This, Index);
2837
2838     /* Validate Index */
2839     if (Index >= This->adapter->gl_info.limits.clipplanes)
2840     {
2841         TRACE("Application has requested clipplane this device doesn't support\n");
2842         return WINED3DERR_INVALIDCALL;
2843     }
2844
2845     pPlane[0] = (float) This->stateBlock->clipplane[Index][0];
2846     pPlane[1] = (float) This->stateBlock->clipplane[Index][1];
2847     pPlane[2] = (float) This->stateBlock->clipplane[Index][2];
2848     pPlane[3] = (float) This->stateBlock->clipplane[Index][3];
2849     return WINED3D_OK;
2850 }
2851
2852 /*****
2853  * Get / Set Clip Plane Status
2854  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2855  *****/
2856 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2857     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2858     FIXME("(%p) : stub\n", This);
2859
2860     if (!pClipStatus)
2861         return WINED3DERR_INVALIDCALL;
2862
2863     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2864     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2865     return WINED3D_OK;
2866 }
2867
2868 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2869     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2870     FIXME("(%p) : stub\n", This);
2871
2872     if (!pClipStatus)
2873         return WINED3DERR_INVALIDCALL;
2874
2875     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2876     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2877     return WINED3D_OK;
2878 }
2879
2880 /*****
2881  * Get / Set Material
2882  *****/
2883 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2884     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2885
2886     This->updateStateBlock->changed.material = TRUE;
2887     This->updateStateBlock->state.material = *pMaterial;
2888
2889     /* Handle recording of state blocks */
2890     if (This->isRecordingState) {
2891         TRACE("Recording... not performing anything\n");
2892         return WINED3D_OK;
2893     }
2894
2895     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_MATERIAL);
2896     return WINED3D_OK;
2897 }
2898
2899 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2900     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2901     *pMaterial = This->updateStateBlock->state.material;
2902     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2903         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2904     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2905         pMaterial->Ambient.b, pMaterial->Ambient.a);
2906     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2907         pMaterial->Specular.b, pMaterial->Specular.a);
2908     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2909         pMaterial->Emissive.b, pMaterial->Emissive.a);
2910     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2911
2912     return WINED3D_OK;
2913 }
2914
2915 /*****
2916  * Get / Set Indices
2917  *****/
2918 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndexBuffer(IWineD3DDevice *iface,
2919         IWineD3DBuffer *pIndexData, enum wined3d_format_id fmt)
2920 {
2921     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2922     IWineD3DBuffer *oldIdxs;
2923
2924     TRACE("(%p) : Setting to %p\n", This, pIndexData);
2925     oldIdxs = This->updateStateBlock->pIndexData;
2926
2927     This->updateStateBlock->changed.indices = TRUE;
2928     This->updateStateBlock->pIndexData = pIndexData;
2929     This->updateStateBlock->IndexFmt = fmt;
2930
2931     /* Handle recording of state blocks */
2932     if (This->isRecordingState) {
2933         TRACE("Recording... not performing anything\n");
2934         if(pIndexData) IWineD3DBuffer_AddRef(pIndexData);
2935         if(oldIdxs) IWineD3DBuffer_Release(oldIdxs);
2936         return WINED3D_OK;
2937     }
2938
2939     if(oldIdxs != pIndexData) {
2940         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2941         if(pIndexData) {
2942             InterlockedIncrement(&((struct wined3d_buffer *)pIndexData)->bind_count);
2943             IWineD3DBuffer_AddRef(pIndexData);
2944         }
2945         if(oldIdxs) {
2946             InterlockedDecrement(&((struct wined3d_buffer *)oldIdxs)->bind_count);
2947             IWineD3DBuffer_Release(oldIdxs);
2948         }
2949     }
2950
2951     return WINED3D_OK;
2952 }
2953
2954 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndexBuffer(IWineD3DDevice *iface, IWineD3DBuffer **ppIndexData)
2955 {
2956     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2957
2958     *ppIndexData = This->stateBlock->pIndexData;
2959
2960     /* up ref count on ppindexdata */
2961     if (*ppIndexData) {
2962         IWineD3DBuffer_AddRef(*ppIndexData);
2963         TRACE("(%p) index data set to %p\n", This, ppIndexData);
2964     }else{
2965         TRACE("(%p) No index data set\n", This);
2966     }
2967     TRACE("Returning %p\n", *ppIndexData);
2968
2969     return WINED3D_OK;
2970 }
2971
2972 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2973 static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, INT BaseIndex) {
2974     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2975     TRACE("(%p)->(%d)\n", This, BaseIndex);
2976
2977     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2978         TRACE("Application is setting the old value over, nothing to do\n");
2979         return WINED3D_OK;
2980     }
2981
2982     This->updateStateBlock->baseVertexIndex = BaseIndex;
2983
2984     if (This->isRecordingState) {
2985         TRACE("Recording... not performing anything\n");
2986         return WINED3D_OK;
2987     }
2988     /* The base vertex index affects the stream sources */
2989     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2990     return WINED3D_OK;
2991 }
2992
2993 static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, INT* base_index) {
2994     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2995     TRACE("(%p) : base_index %p\n", This, base_index);
2996
2997     *base_index = This->stateBlock->baseVertexIndex;
2998
2999     TRACE("Returning %u\n", *base_index);
3000
3001     return WINED3D_OK;
3002 }
3003
3004 /*****
3005  * Get / Set Viewports
3006  *****/
3007 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3008     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3009
3010     TRACE("(%p)\n", This);
3011     This->updateStateBlock->changed.viewport = TRUE;
3012     This->updateStateBlock->state.viewport = *pViewport;
3013
3014     /* Handle recording of state blocks */
3015     if (This->isRecordingState) {
3016         TRACE("Recording... not performing anything\n");
3017         return WINED3D_OK;
3018     }
3019
3020     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3021           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3022
3023     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
3024     return WINED3D_OK;
3025
3026 }
3027
3028 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3029     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3030     TRACE("(%p)\n", This);
3031     *pViewport = This->stateBlock->state.viewport;
3032     return WINED3D_OK;
3033 }
3034
3035 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface,
3036         WINED3DRENDERSTATETYPE State, DWORD Value)
3037 {
3038     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3039     DWORD oldValue = This->stateBlock->state.render_states[State];
3040
3041     TRACE("iface %p, state %s (%#x), value %#x.\n", iface, debug_d3drenderstate(State), State, Value);
3042
3043     This->updateStateBlock->changed.renderState[State >> 5] |= 1 << (State & 0x1f);
3044     This->updateStateBlock->state.render_states[State] = Value;
3045
3046     /* Handle recording of state blocks */
3047     if (This->isRecordingState) {
3048         TRACE("Recording... not performing anything\n");
3049         return WINED3D_OK;
3050     }
3051
3052     /* Compared here and not before the assignment to allow proper stateblock recording */
3053     if(Value == oldValue) {
3054         TRACE("Application is setting the old value over, nothing to do\n");
3055     } else {
3056         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3057     }
3058
3059     return WINED3D_OK;
3060 }
3061
3062 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface,
3063         WINED3DRENDERSTATETYPE State, DWORD *pValue)
3064 {
3065     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3066
3067     TRACE("iface %p, state %s (%#x), value %p.\n", iface, debug_d3drenderstate(State), State, pValue);
3068
3069     *pValue = This->stateBlock->state.render_states[State];
3070     return WINED3D_OK;
3071 }
3072
3073 /*****
3074  * Get / Set Sampler States
3075  * TODO: Verify against dx9 definitions
3076  *****/
3077
3078 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3079     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3080     DWORD oldValue;
3081
3082     TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3083             This, Sampler, debug_d3dsamplerstate(Type), Type, Value);
3084
3085     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3086         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3087     }
3088
3089     if (Sampler >= sizeof(This->stateBlock->state.sampler_states) / sizeof(*This->stateBlock->state.sampler_states))
3090     {
3091         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3092         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3093     }
3094
3095     oldValue = This->stateBlock->state.sampler_states[Sampler][Type];
3096     This->updateStateBlock->state.sampler_states[Sampler][Type] = Value;
3097     This->updateStateBlock->changed.samplerState[Sampler] |= 1 << Type;
3098
3099     /* Handle recording of state blocks */
3100     if (This->isRecordingState) {
3101         TRACE("Recording... not performing anything\n");
3102         return WINED3D_OK;
3103     }
3104
3105     if(oldValue == Value) {
3106         TRACE("Application is setting the old value over, nothing to do\n");
3107         return WINED3D_OK;
3108     }
3109
3110     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3111
3112     return WINED3D_OK;
3113 }
3114
3115 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3116     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3117
3118     TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3119             This, Sampler, debug_d3dsamplerstate(Type), Type);
3120
3121     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3122         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3123     }
3124
3125     if (Sampler >= sizeof(This->stateBlock->state.sampler_states) / sizeof(*This->stateBlock->state.sampler_states))
3126     {
3127         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3128         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3129     }
3130     *Value = This->stateBlock->state.sampler_states[Sampler][Type];
3131     TRACE("(%p) : Returning %#x\n", This, *Value);
3132
3133     return WINED3D_OK;
3134 }
3135
3136 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3137     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3138
3139     This->updateStateBlock->changed.scissorRect = TRUE;
3140     if (EqualRect(&This->updateStateBlock->state.scissor_rect, pRect))
3141     {
3142         TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
3143         return WINED3D_OK;
3144     }
3145     CopyRect(&This->updateStateBlock->state.scissor_rect, pRect);
3146
3147     if(This->isRecordingState) {
3148         TRACE("Recording... not performing anything\n");
3149         return WINED3D_OK;
3150     }
3151
3152     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
3153
3154     return WINED3D_OK;
3155 }
3156
3157 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3158     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3159
3160     *pRect = This->updateStateBlock->state.scissor_rect;
3161     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3162     return WINED3D_OK;
3163 }
3164
3165 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3166     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3167     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3168
3169     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3170
3171     if (pDecl) IWineD3DVertexDeclaration_AddRef(pDecl);
3172     if (oldDecl) IWineD3DVertexDeclaration_Release(oldDecl);
3173
3174     This->updateStateBlock->vertexDecl = pDecl;
3175     This->updateStateBlock->changed.vertexDecl = TRUE;
3176
3177     if (This->isRecordingState) {
3178         TRACE("Recording... not performing anything\n");
3179         return WINED3D_OK;
3180     } else if(pDecl == oldDecl) {
3181         /* Checked after the assignment to allow proper stateblock recording */
3182         TRACE("Application is setting the old declaration over, nothing to do\n");
3183         return WINED3D_OK;
3184     }
3185
3186     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3187     return WINED3D_OK;
3188 }
3189
3190 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3191     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3192
3193     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3194
3195     *ppDecl = This->stateBlock->vertexDecl;
3196     if (*ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3197     return WINED3D_OK;
3198 }
3199
3200 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3201     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3202     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3203
3204     This->updateStateBlock->vertexShader         = pShader;
3205     This->updateStateBlock->changed.vertexShader = TRUE;
3206
3207     if (This->isRecordingState) {
3208         if(pShader) IWineD3DVertexShader_AddRef(pShader);
3209         if(oldShader) IWineD3DVertexShader_Release(oldShader);
3210         TRACE("Recording... not performing anything\n");
3211         return WINED3D_OK;
3212     } else if(oldShader == pShader) {
3213         /* Checked here to allow proper stateblock recording */
3214         TRACE("App is setting the old shader over, nothing to do\n");
3215         return WINED3D_OK;
3216     }
3217
3218     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3219     if(pShader) IWineD3DVertexShader_AddRef(pShader);
3220     if(oldShader) IWineD3DVertexShader_Release(oldShader);
3221
3222     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3223
3224     return WINED3D_OK;
3225 }
3226
3227 static IWineD3DVertexShader * WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface)
3228 {
3229     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
3230     IWineD3DVertexShader *shader;
3231
3232     TRACE("iface %p.\n", iface);
3233
3234     shader = device->stateBlock->vertexShader;
3235     if (shader) IWineD3DVertexShader_AddRef(shader);
3236
3237     TRACE("Returning %p.\n", shader);
3238     return shader;
3239 }
3240
3241 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3242     IWineD3DDevice *iface,
3243     UINT start,
3244     CONST BOOL *srcData,
3245     UINT count) {
3246
3247     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3248     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3249
3250     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3251             iface, srcData, start, count);
3252
3253     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3254
3255     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3256     for (i = 0; i < cnt; i++)
3257         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3258
3259     for (i = start; i < cnt + start; ++i) {
3260         This->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i);
3261     }
3262
3263     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3264
3265     return WINED3D_OK;
3266 }
3267
3268 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3269     IWineD3DDevice *iface,
3270     UINT start,
3271     BOOL *dstData,
3272     UINT count) {
3273
3274     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3275     int cnt = min(count, MAX_CONST_B - start);
3276
3277     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3278             iface, dstData, start, count);
3279
3280     if (!dstData || cnt < 0)
3281         return WINED3DERR_INVALIDCALL;
3282
3283     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3284     return WINED3D_OK;
3285 }
3286
3287 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3288     IWineD3DDevice *iface,
3289     UINT start,
3290     CONST int *srcData,
3291     UINT count) {
3292
3293     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3294     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3295
3296     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3297             iface, srcData, start, count);
3298
3299     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3300
3301     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3302     for (i = 0; i < cnt; i++)
3303         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3304            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3305
3306     for (i = start; i < cnt + start; ++i) {
3307         This->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i);
3308     }
3309
3310     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3311
3312     return WINED3D_OK;
3313 }
3314
3315 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3316     IWineD3DDevice *iface,
3317     UINT start,
3318     int *dstData,
3319     UINT count) {
3320
3321     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3322     int cnt = min(count, MAX_CONST_I - start);
3323
3324     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3325             iface, dstData, start, count);
3326
3327     if (!dstData || ((signed int)MAX_CONST_I - (signed int)start) <= 0)
3328         return WINED3DERR_INVALIDCALL;
3329
3330     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3331     return WINED3D_OK;
3332 }
3333
3334 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3335     IWineD3DDevice *iface,
3336     UINT start,
3337     CONST float *srcData,
3338     UINT count) {
3339
3340     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3341     UINT i;
3342
3343     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3344             iface, srcData, start, count);
3345
3346     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3347     if (!srcData || start + count > This->d3d_vshader_constantF || start > This->d3d_vshader_constantF)
3348         return WINED3DERR_INVALIDCALL;
3349
3350     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3351     if(TRACE_ON(d3d)) {
3352         for (i = 0; i < count; i++)
3353             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3354                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3355     }
3356
3357     if (!This->isRecordingState)
3358     {
3359         This->shader_backend->shader_update_float_vertex_constants(iface, start, count);
3360         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3361     }
3362
3363     memset(This->updateStateBlock->changed.vertexShaderConstantsF + start, 1,
3364             sizeof(*This->updateStateBlock->changed.vertexShaderConstantsF) * count);
3365
3366     return WINED3D_OK;
3367 }
3368
3369 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3370     IWineD3DDevice *iface,
3371     UINT start,
3372     float *dstData,
3373     UINT count) {
3374
3375     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3376     int cnt = min(count, This->d3d_vshader_constantF - start);
3377
3378     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3379             iface, dstData, start, count);
3380
3381     if (!dstData || cnt < 0)
3382         return WINED3DERR_INVALIDCALL;
3383
3384     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3385     return WINED3D_OK;
3386 }
3387
3388 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3389     DWORD i;
3390     for(i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
3391     {
3392         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3393     }
3394 }
3395
3396 static void device_map_stage(IWineD3DDeviceImpl *This, DWORD stage, DWORD unit)
3397 {
3398     DWORD i = This->rev_tex_unit_map[unit];
3399     DWORD j = This->texUnitMap[stage];
3400
3401     This->texUnitMap[stage] = unit;
3402     if (i != WINED3D_UNMAPPED_STAGE && i != stage)
3403     {
3404         This->texUnitMap[i] = WINED3D_UNMAPPED_STAGE;
3405     }
3406
3407     This->rev_tex_unit_map[unit] = stage;
3408     if (j != WINED3D_UNMAPPED_STAGE && j != unit)
3409     {
3410         This->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE;
3411     }
3412 }
3413
3414 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
3415     int i;
3416
3417     This->fixed_function_usage_map = 0;
3418     for (i = 0; i < MAX_TEXTURES; ++i)
3419     {
3420         const struct wined3d_state *state = &This->stateBlock->state;
3421         WINED3DTEXTUREOP color_op = state->texture_states[i][WINED3DTSS_COLOROP];
3422         WINED3DTEXTUREOP alpha_op = state->texture_states[i][WINED3DTSS_ALPHAOP];
3423         DWORD color_arg1 = state->texture_states[i][WINED3DTSS_COLORARG1] & WINED3DTA_SELECTMASK;
3424         DWORD color_arg2 = state->texture_states[i][WINED3DTSS_COLORARG2] & WINED3DTA_SELECTMASK;
3425         DWORD color_arg3 = state->texture_states[i][WINED3DTSS_COLORARG0] & WINED3DTA_SELECTMASK;
3426         DWORD alpha_arg1 = state->texture_states[i][WINED3DTSS_ALPHAARG1] & WINED3DTA_SELECTMASK;
3427         DWORD alpha_arg2 = state->texture_states[i][WINED3DTSS_ALPHAARG2] & WINED3DTA_SELECTMASK;
3428         DWORD alpha_arg3 = state->texture_states[i][WINED3DTSS_ALPHAARG0] & WINED3DTA_SELECTMASK;
3429
3430         if (color_op == WINED3DTOP_DISABLE) {
3431             /* Not used, and disable higher stages */
3432             break;
3433         }
3434
3435         if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG2)
3436                 || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG1)
3437                 || ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP))
3438                 || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
3439                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
3440                 || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
3441             This->fixed_function_usage_map |= (1 << i);
3442         }
3443
3444         if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
3445             This->fixed_function_usage_map |= (1 << (i + 1));
3446         }
3447     }
3448 }
3449
3450 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This, const struct wined3d_gl_info *gl_info)
3451 {
3452     unsigned int i, tex;
3453     WORD ffu_map;
3454
3455     device_update_fixed_function_usage_map(This);
3456     ffu_map = This->fixed_function_usage_map;
3457
3458     if (This->max_ffp_textures == gl_info->limits.texture_stages
3459             || This->stateBlock->state.lowest_disabled_stage <= This->max_ffp_textures)
3460     {
3461         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3462         {
3463             if (!(ffu_map & 1)) continue;
3464
3465             if (This->texUnitMap[i] != i) {
3466                 device_map_stage(This, i, i);
3467                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3468                 markTextureStagesDirty(This, i);
3469             }
3470         }
3471         return;
3472     }
3473
3474     /* Now work out the mapping */
3475     tex = 0;
3476     for (i = 0; ffu_map; ffu_map >>= 1, ++i)
3477     {
3478         if (!(ffu_map & 1)) continue;
3479
3480         if (This->texUnitMap[i] != tex) {
3481             device_map_stage(This, i, tex);
3482             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3483             markTextureStagesDirty(This, i);
3484         }
3485
3486         ++tex;
3487     }
3488 }
3489
3490 static void device_map_psamplers(IWineD3DDeviceImpl *This, const struct wined3d_gl_info *gl_info)
3491 {
3492     const WINED3DSAMPLER_TEXTURE_TYPE *sampler_type =
3493             ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.sampler_type;
3494     unsigned int i;
3495
3496     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
3497         if (sampler_type[i] && This->texUnitMap[i] != i)
3498         {
3499             device_map_stage(This, i, i);
3500             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3501             if (i < gl_info->limits.texture_stages)
3502             {
3503                 markTextureStagesDirty(This, i);
3504             }
3505         }
3506     }
3507 }
3508
3509 static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_tokens,
3510         const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_tokens, DWORD unit)
3511 {
3512     DWORD current_mapping = This->rev_tex_unit_map[unit];
3513
3514     /* Not currently used */
3515     if (current_mapping == WINED3D_UNMAPPED_STAGE) return TRUE;
3516
3517     if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
3518         /* Used by a fragment sampler */
3519
3520         if (!pshader_sampler_tokens) {
3521             /* No pixel shader, check fixed function */
3522             return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping));
3523         }
3524
3525         /* Pixel shader, check the shader's sampler map */
3526         return !pshader_sampler_tokens[current_mapping];
3527     }
3528
3529     /* Used by a vertex sampler */
3530     return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS];
3531 }
3532
3533 static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps, const struct wined3d_gl_info *gl_info)
3534 {
3535     const WINED3DSAMPLER_TEXTURE_TYPE *vshader_sampler_type =
3536             ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.sampler_type;
3537     const WINED3DSAMPLER_TEXTURE_TYPE *pshader_sampler_type = NULL;
3538     int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1;
3539     int i;
3540
3541     if (ps) {
3542         IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
3543
3544         /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3545          * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3546         pshader_sampler_type = pshader->baseShader.reg_maps.sampler_type;
3547     }
3548
3549     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
3550         DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
3551         if (vshader_sampler_type[i])
3552         {
3553             if (This->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
3554             {
3555                 /* Already mapped somewhere */
3556                 continue;
3557             }
3558
3559             while (start >= 0) {
3560                 if (device_unit_free_for_vs(This, pshader_sampler_type, vshader_sampler_type, start))
3561                 {
3562                     device_map_stage(This, vsampler_idx, start);
3563                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx));
3564
3565                     --start;
3566                     break;
3567                 }
3568
3569                 --start;
3570             }
3571         }
3572     }
3573 }
3574
3575 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This)
3576 {
3577     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
3578     BOOL vs = use_vs(This->stateBlock);
3579     BOOL ps = use_ps(This->stateBlock);
3580     /*
3581      * Rules are:
3582      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3583      * that would be really messy and require shader recompilation
3584      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3585      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3586      */
3587     if (ps) device_map_psamplers(This, gl_info);
3588     else device_map_fixed_function_samplers(This, gl_info);
3589
3590     if (vs) device_map_vsamplers(This, ps, gl_info);
3591 }
3592
3593 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3594     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3595     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3596     This->updateStateBlock->pixelShader         = pShader;
3597     This->updateStateBlock->changed.pixelShader = TRUE;
3598
3599     /* Handle recording of state blocks */
3600     if (This->isRecordingState) {
3601         TRACE("Recording... not performing anything\n");
3602     }
3603
3604     if (This->isRecordingState) {
3605         TRACE("Recording... not performing anything\n");
3606         if(pShader) IWineD3DPixelShader_AddRef(pShader);
3607         if(oldShader) IWineD3DPixelShader_Release(oldShader);
3608         return WINED3D_OK;
3609     }
3610
3611     if(pShader == oldShader) {
3612         TRACE("App is setting the old pixel shader over, nothing to do\n");
3613         return WINED3D_OK;
3614     }
3615
3616     if(pShader) IWineD3DPixelShader_AddRef(pShader);
3617     if(oldShader) IWineD3DPixelShader_Release(oldShader);
3618
3619     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3620     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3621
3622     return WINED3D_OK;
3623 }
3624
3625 static IWineD3DPixelShader * WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface)
3626 {
3627     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
3628     IWineD3DPixelShader *shader;
3629
3630     TRACE("iface %p.\n", iface);
3631
3632     shader = device->stateBlock->pixelShader;
3633     if (shader) IWineD3DPixelShader_AddRef(shader);
3634
3635     TRACE("Returning %p.\n", shader);
3636     return shader;
3637 }
3638
3639 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3640     IWineD3DDevice *iface,
3641     UINT start,
3642     CONST BOOL *srcData,
3643     UINT count) {
3644
3645     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3646     unsigned int i, cnt = min(count, MAX_CONST_B - start);
3647
3648     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3649             iface, srcData, start, count);
3650
3651     if (!srcData || start >= MAX_CONST_B) return WINED3DERR_INVALIDCALL;
3652
3653     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3654     for (i = 0; i < cnt; i++)
3655         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3656
3657     for (i = start; i < cnt + start; ++i) {
3658         This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i);
3659     }
3660
3661     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3662
3663     return WINED3D_OK;
3664 }
3665
3666 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3667     IWineD3DDevice *iface,
3668     UINT start,
3669     BOOL *dstData,
3670     UINT count) {
3671
3672     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3673     int cnt = min(count, MAX_CONST_B - start);
3674
3675     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3676             iface, dstData, start, count);
3677
3678     if (!dstData || cnt < 0)
3679         return WINED3DERR_INVALIDCALL;
3680
3681     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3682     return WINED3D_OK;
3683 }
3684
3685 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3686     IWineD3DDevice *iface,
3687     UINT start,
3688     CONST int *srcData,
3689     UINT count) {
3690
3691     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3692     unsigned int i, cnt = min(count, MAX_CONST_I - start);
3693
3694     TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3695             iface, srcData, start, count);
3696
3697     if (!srcData || start >= MAX_CONST_I) return WINED3DERR_INVALIDCALL;
3698
3699     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3700     for (i = 0; i < cnt; i++)
3701         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3702            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3703
3704     for (i = start; i < cnt + start; ++i) {
3705         This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i);
3706     }
3707
3708     if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3709
3710     return WINED3D_OK;
3711 }
3712
3713 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3714     IWineD3DDevice *iface,
3715     UINT start,
3716     int *dstData,
3717     UINT count) {
3718
3719     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3720     int cnt = min(count, MAX_CONST_I - start);
3721
3722     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3723             iface, dstData, start, count);
3724
3725     if (!dstData || cnt < 0)
3726         return WINED3DERR_INVALIDCALL;
3727
3728     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3729     return WINED3D_OK;
3730 }
3731
3732 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3733     IWineD3DDevice *iface,
3734     UINT start,
3735     CONST float *srcData,
3736     UINT count) {
3737
3738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3739     UINT i;
3740
3741     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3742             iface, srcData, start, count);
3743
3744     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3745     if (!srcData || start + count > This->d3d_pshader_constantF || start > This->d3d_pshader_constantF)
3746         return WINED3DERR_INVALIDCALL;
3747
3748     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3749     if(TRACE_ON(d3d)) {
3750         for (i = 0; i < count; i++)
3751             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3752                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3753     }
3754
3755     if (!This->isRecordingState)
3756     {
3757         This->shader_backend->shader_update_float_pixel_constants(iface, start, count);
3758         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3759     }
3760
3761     memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1,
3762             sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count);
3763
3764     return WINED3D_OK;
3765 }
3766
3767 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3768     IWineD3DDevice *iface,
3769     UINT start,
3770     float *dstData,
3771     UINT count) {
3772
3773     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3774     int cnt = min(count, This->d3d_pshader_constantF - start);
3775
3776     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3777             iface, dstData, start, count);
3778
3779     if (!dstData || cnt < 0)
3780         return WINED3DERR_INVALIDCALL;
3781
3782     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3783     return WINED3D_OK;
3784 }
3785
3786 /* Context activation is done by the caller. */
3787 /* Do not call while under the GL lock. */
3788 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3789 static HRESULT process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount,
3790         const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD dwFlags,
3791         DWORD DestFVF)
3792 {
3793     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
3794     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3795     unsigned int i;
3796     WINED3DVIEWPORT vp;
3797     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3798     BOOL doClip;
3799     DWORD numTextures;
3800
3801     if (stream_info->use_map & (1 << WINED3D_FFP_NORMAL))
3802     {
3803         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3804     }
3805
3806     if (!(stream_info->use_map & (1 << WINED3D_FFP_POSITION)))
3807     {
3808         ERR("Source has no position mask\n");
3809         return WINED3DERR_INVALIDCALL;
3810     }
3811
3812     if (!dest->resource.allocatedMemory)
3813         buffer_get_sysmem(dest, gl_info);
3814
3815     /* Get a pointer into the destination vbo(create one if none exists) and
3816      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3817      */
3818     if (!dest->buffer_object && gl_info->supported[ARB_VERTEX_BUFFER_OBJECT])
3819     {
3820         dest->flags |= WINED3D_BUFFER_CREATEBO;
3821         IWineD3DBuffer_PreLoad((IWineD3DBuffer *)dest);
3822     }
3823
3824     if (dest->buffer_object)
3825     {
3826         unsigned char extrabytes = 0;
3827         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3828          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3829          * this may write 4 extra bytes beyond the area that should be written
3830          */
3831         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
3832         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
3833         if(!dest_conv_addr) {
3834             ERR("Out of memory\n");
3835             /* Continue without storing converted vertices */
3836         }
3837         dest_conv = dest_conv_addr;
3838     }
3839
3840     if (This->stateBlock->state.render_states[WINED3DRS_CLIPPING])
3841     {
3842         static BOOL warned = FALSE;
3843         /*
3844          * The clipping code is not quite correct. Some things need
3845          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3846          * so disable clipping for now.
3847          * (The graphics in Half-Life are broken, and my processvertices
3848          *  test crashes with IDirect3DDevice3)
3849         doClip = TRUE;
3850          */
3851         doClip = FALSE;
3852         if(!warned) {
3853            warned = TRUE;
3854            FIXME("Clipping is broken and disabled for now\n");
3855         }
3856     } else doClip = FALSE;
3857     dest_ptr = ((char *)buffer_get_sysmem(dest, gl_info)) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3858
3859     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3860                                  WINED3DTS_VIEW,
3861                                  &view_mat);
3862     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3863                                  WINED3DTS_PROJECTION,
3864                                  &proj_mat);
3865     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3866                                  WINED3DTS_WORLDMATRIX(0),
3867                                  &world_mat);
3868
3869     TRACE("View mat:\n");
3870     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);
3871     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);
3872     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);
3873     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);
3874
3875     TRACE("Proj mat:\n");
3876     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);
3877     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);
3878     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);
3879     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);
3880
3881     TRACE("World mat:\n");
3882     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);
3883     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);
3884     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);
3885     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);
3886
3887     /* Get the viewport */
3888     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3889     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3890           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3891
3892     multiply_matrix(&mat,&view_mat,&world_mat);
3893     multiply_matrix(&mat,&proj_mat,&mat);
3894
3895     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3896
3897     for (i = 0; i < dwCount; i+= 1) {
3898         unsigned int tex_index;
3899
3900         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3901              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3902             /* The position first */
3903             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_POSITION];
3904             const float *p = (const float *)(element->data + i * element->stride);
3905             float x, y, z, rhw;
3906             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3907
3908             /* Multiplication with world, view and projection matrix */
3909             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);
3910             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);
3911             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);
3912             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);
3913
3914             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3915
3916             /* WARNING: The following things are taken from d3d7 and were not yet checked
3917              * against d3d8 or d3d9!
3918              */
3919
3920             /* Clipping conditions: From msdn
3921              *
3922              * A vertex is clipped if it does not match the following requirements
3923              * -rhw < x <= rhw
3924              * -rhw < y <= rhw
3925              *    0 < z <= rhw
3926              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3927              *
3928              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3929              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3930              *
3931              */
3932
3933             if( !doClip ||
3934                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3935                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3936                   ( rhw > eps ) ) ) {
3937
3938                 /* "Normal" viewport transformation (not clipped)
3939                  * 1) The values are divided by rhw
3940                  * 2) The y axis is negative, so multiply it with -1
3941                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3942                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3943                  * 4) Multiply x with Width/2 and add Width/2
3944                  * 5) The same for the height
3945                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3946                  *    The minimum Z value to z
3947                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3948                  *
3949                  * Well, basically it's simply a linear transformation into viewport
3950                  * coordinates
3951                  */
3952
3953                 x /= rhw;
3954                 y /= rhw;
3955                 z /= rhw;
3956
3957                 y *= -1;
3958
3959                 x *= vp.Width / 2;
3960                 y *= vp.Height / 2;
3961                 z *= vp.MaxZ - vp.MinZ;
3962
3963                 x += vp.Width / 2 + vp.X;
3964                 y += vp.Height / 2 + vp.Y;
3965                 z += vp.MinZ;
3966
3967                 rhw = 1 / rhw;
3968             } else {
3969                 /* That vertex got clipped
3970                  * Contrary to OpenGL it is not dropped completely, it just
3971                  * undergoes a different calculation.
3972                  */
3973                 TRACE("Vertex got clipped\n");
3974                 x += rhw;
3975                 y += rhw;
3976
3977                 x  /= 2;
3978                 y  /= 2;
3979
3980                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3981                  * outside of the main vertex buffer memory. That needs some more
3982                  * investigation...
3983                  */
3984             }
3985
3986             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3987
3988
3989             ( (float *) dest_ptr)[0] = x;
3990             ( (float *) dest_ptr)[1] = y;
3991             ( (float *) dest_ptr)[2] = z;
3992             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3993
3994             dest_ptr += 3 * sizeof(float);
3995
3996             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3997                 dest_ptr += sizeof(float);
3998             }
3999
4000             if(dest_conv) {
4001                 float w = 1 / rhw;
4002                 ( (float *) dest_conv)[0] = x * w;
4003                 ( (float *) dest_conv)[1] = y * w;
4004                 ( (float *) dest_conv)[2] = z * w;
4005                 ( (float *) dest_conv)[3] = w;
4006
4007                 dest_conv += 3 * sizeof(float);
4008
4009                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4010                     dest_conv += sizeof(float);
4011                 }
4012             }
4013         }
4014         if (DestFVF & WINED3DFVF_PSIZE) {
4015             dest_ptr += sizeof(DWORD);
4016             if(dest_conv) dest_conv += sizeof(DWORD);
4017         }
4018         if (DestFVF & WINED3DFVF_NORMAL) {
4019             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_NORMAL];
4020             const float *normal = (const float *)(element->data + i * element->stride);
4021             /* AFAIK this should go into the lighting information */
4022             FIXME("Didn't expect the destination to have a normal\n");
4023             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4024             if(dest_conv) {
4025                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4026             }
4027         }
4028
4029         if (DestFVF & WINED3DFVF_DIFFUSE) {
4030             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE];
4031             const DWORD *color_d = (const DWORD *)(element->data + i * element->stride);
4032             if (!(stream_info->use_map & (1 << WINED3D_FFP_DIFFUSE)))
4033             {
4034                 static BOOL warned = FALSE;
4035
4036                 if(!warned) {
4037                     ERR("No diffuse color in source, but destination has one\n");
4038                     warned = TRUE;
4039                 }
4040
4041                 *( (DWORD *) dest_ptr) = 0xffffffff;
4042                 dest_ptr += sizeof(DWORD);
4043
4044                 if(dest_conv) {
4045                     *( (DWORD *) dest_conv) = 0xffffffff;
4046                     dest_conv += sizeof(DWORD);
4047                 }
4048             }
4049             else {
4050                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4051                 if(dest_conv) {
4052                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4053                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4054                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4055                     dest_conv += sizeof(DWORD);
4056                 }
4057             }
4058         }
4059
4060         if (DestFVF & WINED3DFVF_SPECULAR)
4061         {
4062             /* What's the color value in the feedback buffer? */
4063             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR];
4064             const DWORD *color_s = (const DWORD *)(element->data + i * element->stride);
4065             if (!(stream_info->use_map & (1 << WINED3D_FFP_SPECULAR)))
4066             {
4067                 static BOOL warned = FALSE;
4068
4069                 if(!warned) {
4070                     ERR("No specular color in source, but destination has one\n");
4071                     warned = TRUE;
4072                 }
4073
4074                 *( (DWORD *) dest_ptr) = 0xFF000000;
4075                 dest_ptr += sizeof(DWORD);
4076
4077                 if(dest_conv) {
4078                     *( (DWORD *) dest_conv) = 0xFF000000;
4079                     dest_conv += sizeof(DWORD);
4080                 }
4081             }
4082             else {
4083                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4084                 if(dest_conv) {
4085                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4086                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4087                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4088                     dest_conv += sizeof(DWORD);
4089                 }
4090             }
4091         }
4092
4093         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4094             const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
4095             const float *tex_coord = (const float *)(element->data + i * element->stride);
4096             if (!(stream_info->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + tex_index))))
4097             {
4098                 ERR("No source texture, but destination requests one\n");
4099                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4100                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4101             }
4102             else {
4103                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4104                 if(dest_conv) {
4105                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4106                 }
4107             }
4108         }
4109     }
4110
4111     if (dest_conv)
4112     {
4113         ENTER_GL();
4114
4115         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->buffer_object));
4116         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4117         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
4118                                       dwCount * get_flexible_vertex_size(DestFVF),
4119                                       dest_conv_addr));
4120         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4121
4122         LEAVE_GL();
4123
4124         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
4125     }
4126
4127     return WINED3D_OK;
4128 }
4129 #undef copy_and_next
4130
4131 /* Do not call while under the GL lock. */
4132 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex,
4133         UINT VertexCount, IWineD3DBuffer *pDestBuffer, IWineD3DVertexDeclaration *pVertexDecl, DWORD Flags,
4134         DWORD DestFVF)
4135 {
4136     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4137     struct wined3d_stream_info stream_info;
4138     const struct wined3d_gl_info *gl_info;
4139     struct wined3d_context *context;
4140     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
4141     HRESULT hr;
4142
4143     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4144
4145     if(pVertexDecl) {
4146         ERR("Output vertex declaration not implemented yet\n");
4147     }
4148
4149     /* Need any context to write to the vbo. */
4150     context = context_acquire(This, NULL);
4151     gl_info = context->gl_info;
4152
4153     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4154      * control the streamIsUP flag, thus restore it afterwards.
4155      */
4156     This->stateBlock->streamIsUP = FALSE;
4157     device_stream_info_from_declaration(This, FALSE, &stream_info, &vbo);
4158     This->stateBlock->streamIsUP = streamWasUP;
4159
4160     if(vbo || SrcStartIndex) {
4161         unsigned int i;
4162         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4163          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4164          *
4165          * Also get the start index in, but only loop over all elements if there's something to add at all.
4166          */
4167         for (i = 0; i < (sizeof(stream_info.elements) / sizeof(*stream_info.elements)); ++i)
4168         {
4169             struct wined3d_stream_info_element *e;
4170
4171             if (!(stream_info.use_map & (1 << i))) continue;
4172
4173             e = &stream_info.elements[i];
4174             if (e->buffer_object)
4175             {
4176                 struct wined3d_buffer *vb = This->stateBlock->streams[e->stream_idx].buffer;
4177                 e->buffer_object = 0;
4178                 e->data = (BYTE *)((ULONG_PTR)e->data + (ULONG_PTR)buffer_get_sysmem(vb, gl_info));
4179                 ENTER_GL();
4180                 GL_EXTCALL(glDeleteBuffersARB(1, &vb->buffer_object));
4181                 vb->buffer_object = 0;
4182                 LEAVE_GL();
4183             }
4184             if (e->data) e->data += e->stride * SrcStartIndex;
4185         }
4186     }
4187
4188     hr = process_vertices_strided(This, DestIndex, VertexCount, &stream_info,
4189             (struct wined3d_buffer *)pDestBuffer, Flags, DestFVF);
4190
4191     context_release(context);
4192
4193     return hr;
4194 }
4195
4196 /*****
4197  * Get / Set Texture Stage States
4198  * TODO: Verify against dx9 definitions
4199  *****/
4200 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value)
4201 {
4202     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4203     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4204     DWORD oldValue;
4205
4206     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4207
4208     if (Type > WINED3D_HIGHEST_TEXTURE_STATE)
4209     {
4210         WARN("Invalid Type %d passed.\n", Type);
4211         return WINED3D_OK;
4212     }
4213
4214     if (Stage >= gl_info->limits.texture_stages)
4215     {
4216         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
4217                 Stage, gl_info->limits.texture_stages - 1);
4218         return WINED3D_OK;
4219     }
4220
4221     oldValue = This->updateStateBlock->state.texture_states[Stage][Type];
4222     This->updateStateBlock->changed.textureState[Stage] |= 1 << Type;
4223     This->updateStateBlock->state.texture_states[Stage][Type] = Value;
4224
4225     if (This->isRecordingState) {
4226         TRACE("Recording... not performing anything\n");
4227         return WINED3D_OK;
4228     }
4229
4230     /* Checked after the assignments to allow proper stateblock recording */
4231     if(oldValue == Value) {
4232         TRACE("App is setting the old value over, nothing to do\n");
4233         return WINED3D_OK;
4234     }
4235
4236     if (Stage > This->stateBlock->state.lowest_disabled_stage
4237             && This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative
4238             == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP))
4239     {
4240         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4241          * Changes in other states are important on disabled stages too
4242          */
4243         return WINED3D_OK;
4244     }
4245
4246     if(Type == WINED3DTSS_COLOROP) {
4247         unsigned int i;
4248
4249         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4250             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4251              * they have to be disabled
4252              *
4253              * The current stage is dirtified below.
4254              */
4255             for (i = Stage + 1; i < This->stateBlock->state.lowest_disabled_stage; ++i)
4256             {
4257                 TRACE("Additionally dirtifying stage %u\n", i);
4258                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4259             }
4260             This->stateBlock->state.lowest_disabled_stage = Stage;
4261             TRACE("New lowest disabled: %u\n", Stage);
4262         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4263             /* Previously disabled stage enabled. Stages above it may need enabling
4264              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4265              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4266              *
4267              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4268              */
4269
4270             for (i = Stage + 1; i < This->adapter->gl_info.limits.texture_stages; ++i)
4271             {
4272                 if (This->updateStateBlock->state.texture_states[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE)
4273                     break;
4274                 TRACE("Additionally dirtifying stage %u due to enable\n", i);
4275                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4276             }
4277             This->stateBlock->state.lowest_disabled_stage = i;
4278             TRACE("New lowest disabled: %u\n", i);
4279         }
4280     }
4281
4282     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4283
4284     return WINED3D_OK;
4285 }
4286
4287 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD *pValue)
4288 {
4289     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4290
4291     TRACE("iface %p, stage %u, state %s, value %p.\n",
4292             iface, Stage, debug_d3dtexturestate(Type), pValue);
4293
4294     if (Type > WINED3D_HIGHEST_TEXTURE_STATE)
4295     {
4296         WARN("Invalid Type %d passed.\n", Type);
4297         return WINED3D_OK;
4298     }
4299
4300     *pValue = This->updateStateBlock->state.texture_states[Stage][Type];
4301     TRACE("Returning %#x.\n", *pValue);
4302
4303     return WINED3D_OK;
4304 }
4305
4306 /*****
4307  * Get / Set Texture
4308  *****/
4309 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface,
4310         DWORD stage, IWineD3DBaseTexture *texture)
4311 {
4312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4313     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4314     IWineD3DBaseTexture *prev;
4315
4316     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4317
4318     if (stage >= WINED3DVERTEXTEXTURESAMPLER0 && stage <= WINED3DVERTEXTEXTURESAMPLER3)
4319         stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4320
4321     /* Windows accepts overflowing this array... we do not. */
4322     if (stage >= sizeof(This->stateBlock->textures) / sizeof(*This->stateBlock->textures))
4323     {
4324         WARN("Ignoring invalid stage %u.\n", stage);
4325         return WINED3D_OK;
4326     }
4327
4328     /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4329     if (texture && ((IWineD3DTextureImpl *)texture)->resource.pool == WINED3DPOOL_SCRATCH)
4330     {
4331         WARN("Rejecting attempt to set scratch texture.\n");
4332         return WINED3DERR_INVALIDCALL;
4333     }
4334
4335     This->updateStateBlock->changed.textures |= 1 << stage;
4336
4337     prev = This->updateStateBlock->textures[stage];
4338     TRACE("Previous texture %p.\n", prev);
4339
4340     if (texture == prev)
4341     {
4342         TRACE("App is setting the same texture again, nothing to do.\n");
4343         return WINED3D_OK;
4344     }
4345
4346     TRACE("Setting new texture to %p.\n", texture);
4347     This->updateStateBlock->textures[stage] = texture;
4348
4349     if (This->isRecordingState)
4350     {
4351         TRACE("Recording... not performing anything\n");
4352
4353         if (texture) IWineD3DBaseTexture_AddRef(texture);
4354         if (prev) IWineD3DBaseTexture_Release(prev);
4355
4356         return WINED3D_OK;
4357     }
4358
4359     if (texture)
4360     {
4361         IWineD3DBaseTextureImpl *t = (IWineD3DBaseTextureImpl *)texture;
4362         LONG bind_count = InterlockedIncrement(&t->baseTexture.bindCount);
4363         UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
4364
4365         IWineD3DBaseTexture_AddRef(texture);
4366
4367         if (!prev || dimensions != IWineD3DBaseTexture_GetTextureDimensions(prev))
4368         {
4369             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
4370         }
4371
4372         if (!prev && stage < gl_info->limits.texture_stages)
4373         {
4374             /* The source arguments for color and alpha ops have different
4375              * meanings when a NULL texture is bound, so the COLOROP and
4376              * ALPHAOP have to be dirtified. */
4377             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_COLOROP));
4378             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_ALPHAOP));
4379         }
4380
4381         if (bind_count == 1) t->baseTexture.sampler = stage;
4382     }
4383
4384     if (prev)
4385     {
4386         IWineD3DBaseTextureImpl *t = (IWineD3DBaseTextureImpl *)prev;
4387         LONG bind_count = InterlockedDecrement(&t->baseTexture.bindCount);
4388
4389         IWineD3DBaseTexture_Release(prev);
4390
4391         if (!texture && stage < gl_info->limits.texture_stages)
4392         {
4393             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_COLOROP));
4394             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, WINED3DTSS_ALPHAOP));
4395         }
4396
4397         if (bind_count && t->baseTexture.sampler == stage)
4398         {
4399             unsigned int i;
4400
4401             /* Search for other stages the texture is bound to. Shouldn't
4402              * happen if applications bind textures to a single stage only. */
4403             TRACE("Searching for other stages the texture is bound to.\n");
4404             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
4405             {
4406                 if (This->updateStateBlock->textures[i] == prev)
4407                 {
4408                     TRACE("Texture is also bound to stage %u.\n", i);
4409                     t->baseTexture.sampler = i;
4410                     break;
4411                 }
4412             }
4413         }
4414     }
4415
4416     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(stage));
4417
4418     return WINED3D_OK;
4419 }
4420
4421 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4422     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4423
4424     TRACE("(%p) : Stage %#x, ppTexture %p\n", This, Stage, ppTexture);
4425
4426     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4427         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4428     }
4429
4430     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4431         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4432         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4433     }
4434
4435     *ppTexture=This->stateBlock->textures[Stage];
4436     if (*ppTexture)
4437         IWineD3DBaseTexture_AddRef(*ppTexture);
4438
4439     TRACE("(%p) : Returning %p\n", This, *ppTexture);
4440
4441     return WINED3D_OK;
4442 }
4443
4444 /*****
4445  * Get Back Buffer
4446  *****/
4447 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT swapchain_idx,
4448         UINT backbuffer_idx, WINED3DBACKBUFFER_TYPE backbuffer_type, IWineD3DSurface **backbuffer)
4449 {
4450     IWineD3DSwapChain *swapchain;
4451     HRESULT hr;
4452
4453     TRACE("iface %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
4454             iface, swapchain_idx, backbuffer_idx, backbuffer_type, backbuffer);
4455
4456     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
4457     if (FAILED(hr))
4458     {
4459         WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx, hr);
4460         return hr;
4461     }
4462
4463     hr = IWineD3DSwapChain_GetBackBuffer(swapchain, backbuffer_idx, backbuffer_type, backbuffer);
4464     IWineD3DSwapChain_Release(swapchain);
4465     if (FAILED(hr))
4466     {
4467         WARN("Failed to get backbuffer %u, hr %#x.\n", backbuffer_idx, hr);
4468         return hr;
4469     }
4470
4471     return WINED3D_OK;
4472 }
4473
4474 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4475     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4476     WARN("(%p) : stub, calling idirect3d for now\n", This);
4477     return IWineD3D_GetDeviceCaps(This->wined3d, This->adapter->ordinal, This->devType, pCaps);
4478 }
4479
4480 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4482     IWineD3DSwapChain *swapChain;
4483     HRESULT hr;
4484
4485     if(iSwapChain > 0) {
4486         hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4487         if (hr == WINED3D_OK) {
4488             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4489             IWineD3DSwapChain_Release(swapChain);
4490         } else {
4491             FIXME("(%p) Error getting display mode\n", This);
4492         }
4493     } else {
4494         /* Don't read the real display mode,
4495            but return the stored mode instead. X11 can't change the color
4496            depth, and some apps are pretty angry if they SetDisplayMode from
4497            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4498
4499            Also don't relay to the swapchain because with ddraw it's possible
4500            that there isn't a swapchain at all */
4501         pMode->Width = This->ddraw_width;
4502         pMode->Height = This->ddraw_height;
4503         pMode->Format = This->ddraw_format;
4504         pMode->RefreshRate = 0;
4505         hr = WINED3D_OK;
4506     }
4507
4508     return hr;
4509 }
4510
4511 /*****
4512  * Stateblock related functions
4513  *****/
4514
4515 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4516     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4517     IWineD3DStateBlock *stateblock;
4518     HRESULT hr;
4519
4520     TRACE("(%p)\n", This);
4521
4522     if (This->isRecordingState) return WINED3DERR_INVALIDCALL;
4523
4524     hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock);
4525     if (FAILED(hr)) return hr;
4526
4527     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4528     This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock;
4529     This->isRecordingState = TRUE;
4530
4531     TRACE("(%p) recording stateblock %p\n", This, stateblock);
4532
4533     return WINED3D_OK;
4534 }
4535
4536 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4537     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4538     IWineD3DStateBlockImpl *object = This->updateStateBlock;
4539
4540     if (!This->isRecordingState) {
4541         WARN("(%p) not recording! returning error\n", This);
4542         *ppStateBlock = NULL;
4543         return WINED3DERR_INVALIDCALL;
4544     }
4545
4546     stateblock_init_contained_states(object);
4547
4548     *ppStateBlock = (IWineD3DStateBlock*) object;
4549     This->isRecordingState = FALSE;
4550     This->updateStateBlock = This->stateBlock;
4551     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4552     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4553     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4554     return WINED3D_OK;
4555 }
4556
4557 /*****
4558  * Scene related functions
4559  *****/
4560 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4561     /* At the moment we have no need for any functionality at the beginning
4562        of a scene                                                          */
4563     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4564     TRACE("(%p)\n", This);
4565
4566     if(This->inScene) {
4567         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4568         return WINED3DERR_INVALIDCALL;
4569     }
4570     This->inScene = TRUE;
4571     return WINED3D_OK;
4572 }
4573
4574 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface)
4575 {
4576     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4577     struct wined3d_context *context;
4578
4579     TRACE("(%p)\n", This);
4580
4581     if(!This->inScene) {
4582         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4583         return WINED3DERR_INVALIDCALL;
4584     }
4585
4586     context = context_acquire(This, NULL);
4587     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4588     wglFlush();
4589     /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4590      * fails. */
4591     context_release(context);
4592
4593     This->inScene = FALSE;
4594     return WINED3D_OK;
4595 }
4596
4597 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4598         const RECT *pSourceRect, const RECT *pDestRect,
4599         HWND hDestWindowOverride, const RGNDATA *pDirtyRegion)
4600 {
4601     IWineD3DSwapChain *swapChain = NULL;
4602     int i;
4603     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4604
4605     TRACE("iface %p.\n", iface);
4606
4607     for(i = 0 ; i < swapchains ; i ++) {
4608
4609         IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain);
4610         TRACE("Presenting chain %d, %p.\n", i, swapChain);
4611         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4612         IWineD3DSwapChain_Release(swapChain);
4613     }
4614
4615     return WINED3D_OK;
4616 }
4617
4618 /* Do not call while under the GL lock. */
4619 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD rect_count,
4620         const RECT *rects, DWORD flags, WINED3DCOLOR color, float depth, DWORD stencil)
4621 {
4622     const WINED3DCOLORVALUE c = {D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color)};
4623     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
4624     RECT draw_rect;
4625
4626     TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n",
4627             iface, rect_count, rects, flags, color, depth, stencil);
4628
4629     if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && !device->depth_stencil)
4630     {
4631         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4632         /* TODO: What about depth stencil buffers without stencil bits? */
4633         return WINED3DERR_INVALIDCALL;
4634     }
4635
4636     device_get_draw_rect(device, &draw_rect);
4637
4638     return device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
4639             device->render_targets, rect_count, rects, &draw_rect, flags, &c, depth, stencil);
4640 }
4641
4642 /*****
4643  * Drawing functions
4644  *****/
4645
4646 static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice *iface,
4647         WINED3DPRIMITIVETYPE primitive_type)
4648 {
4649     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4650
4651     TRACE("iface %p, primitive_type %s\n", iface, debug_d3dprimitivetype(primitive_type));
4652
4653     This->updateStateBlock->changed.primitive_type = TRUE;
4654     This->updateStateBlock->gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
4655 }
4656
4657 static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice *iface,
4658         WINED3DPRIMITIVETYPE *primitive_type)
4659 {
4660     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4661
4662     TRACE("iface %p, primitive_type %p\n", iface, primitive_type);
4663
4664     *primitive_type = d3d_primitive_type_from_gl(This->stateBlock->gl_primitive_type);
4665
4666     TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type));
4667 }
4668
4669 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, UINT StartVertex, UINT vertex_count)
4670 {
4671     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4672
4673     TRACE("(%p) : start %u, count %u\n", This, StartVertex, vertex_count);
4674
4675     if(!This->stateBlock->vertexDecl) {
4676         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4677         return WINED3DERR_INVALIDCALL;
4678     }
4679
4680     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4681     if(This->stateBlock->streamIsUP) {
4682         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4683         This->stateBlock->streamIsUP = FALSE;
4684     }
4685
4686     if (This->stateBlock->loadBaseVertexIndex)
4687     {
4688         This->stateBlock->loadBaseVertexIndex = 0;
4689         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4690     }
4691     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4692     drawPrimitive(iface, vertex_count, StartVertex /* start_idx */, 0 /* indxSize */, NULL /* indxData */);
4693     return WINED3D_OK;
4694 }
4695
4696 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, UINT startIndex, UINT index_count)
4697 {
4698     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4699     UINT                 idxStride = 2;
4700     IWineD3DBuffer *pIB;
4701     GLuint vbo;
4702
4703     pIB = This->stateBlock->pIndexData;
4704     if (!pIB) {
4705         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4706          * without an index buffer set. (The first time at least...)
4707          * D3D8 simply dies, but I doubt it can do much harm to return
4708          * D3DERR_INVALIDCALL there as well. */
4709         WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4710         return WINED3DERR_INVALIDCALL;
4711     }
4712
4713     if(!This->stateBlock->vertexDecl) {
4714         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4715         return WINED3DERR_INVALIDCALL;
4716     }
4717
4718     if(This->stateBlock->streamIsUP) {
4719         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4720         This->stateBlock->streamIsUP = FALSE;
4721     }
4722     vbo = ((struct wined3d_buffer *) pIB)->buffer_object;
4723
4724     TRACE("(%p) : startIndex %u, index count %u.\n", This, startIndex, index_count);
4725
4726     if (This->stateBlock->IndexFmt == WINED3DFMT_R16_UINT) {
4727         idxStride = 2;
4728     } else {
4729         idxStride = 4;
4730     }
4731
4732     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4733         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4734         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4735     }
4736
4737     drawPrimitive(iface, index_count, startIndex, idxStride,
4738             vbo ? NULL : ((struct wined3d_buffer *)pIB)->resource.allocatedMemory);
4739
4740     return WINED3D_OK;
4741 }
4742
4743 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, UINT vertex_count,
4744         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4745 {
4746     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4747     struct wined3d_stream_state *stream;
4748     IWineD3DBuffer *vb;
4749
4750     TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4751             This, vertex_count, pVertexStreamZeroData, VertexStreamZeroStride);
4752
4753     if(!This->stateBlock->vertexDecl) {
4754         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4755         return WINED3DERR_INVALIDCALL;
4756     }
4757
4758     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4759     stream = &This->stateBlock->streams[0];
4760     vb = (IWineD3DBuffer *)stream->buffer;
4761     stream->buffer = (struct wined3d_buffer *)pVertexStreamZeroData;
4762     if (vb) IWineD3DBuffer_Release(vb);
4763     stream->offset = 0;
4764     stream->stride = VertexStreamZeroStride;
4765     This->stateBlock->streamIsUP = TRUE;
4766     This->stateBlock->loadBaseVertexIndex = 0;
4767
4768     /* TODO: Only mark dirty if drawing from a different UP address */
4769     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4770
4771     drawPrimitive(iface, vertex_count, 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */);
4772
4773     /* MSDN specifies stream zero settings must be set to NULL */
4774     stream->buffer = NULL;
4775     stream->stride = 0;
4776
4777     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4778      * the new stream sources or use UP drawing again
4779      */
4780     return WINED3D_OK;
4781 }
4782
4783 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
4784         UINT index_count, const void *pIndexData, enum wined3d_format_id IndexDataFormat,
4785         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
4786 {
4787     int                 idxStride;
4788     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4789     struct wined3d_stream_state *stream;
4790     IWineD3DBuffer *vb;
4791     IWineD3DBuffer *ib;
4792
4793     TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4794             This, index_count, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4795
4796     if(!This->stateBlock->vertexDecl) {
4797         WARN("(%p) : Called without a valid vertex declaration set\n", This);
4798         return WINED3DERR_INVALIDCALL;
4799     }
4800
4801     if (IndexDataFormat == WINED3DFMT_R16_UINT) {
4802         idxStride = 2;
4803     } else {
4804         idxStride = 4;
4805     }
4806
4807     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4808     stream = &This->stateBlock->streams[0];
4809     vb = (IWineD3DBuffer *)stream->buffer;
4810     stream->buffer = (struct wined3d_buffer *)pVertexStreamZeroData;
4811     if (vb) IWineD3DBuffer_Release(vb);
4812     stream->offset = 0;
4813     stream->stride = VertexStreamZeroStride;
4814     This->stateBlock->streamIsUP = TRUE;
4815
4816     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4817     This->stateBlock->baseVertexIndex = 0;
4818     This->stateBlock->loadBaseVertexIndex = 0;
4819     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4820     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4821     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4822
4823     drawPrimitive(iface, index_count, 0 /* start_idx */, idxStride, pIndexData);
4824
4825     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4826     stream->buffer = NULL;
4827     stream->stride = 0;
4828     ib = This->stateBlock->pIndexData;
4829     if(ib) {
4830         IWineD3DBuffer_Release(ib);
4831         This->stateBlock->pIndexData = NULL;
4832     }
4833     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4834      * SetStreamSource to specify a vertex buffer
4835      */
4836
4837     return WINED3D_OK;
4838 }
4839
4840 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *iface,
4841         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData)
4842 {
4843     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4844
4845     /* Mark the state dirty until we have nicer tracking
4846      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4847      * that value.
4848      */
4849     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4850     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4851     This->stateBlock->baseVertexIndex = 0;
4852     This->up_strided = DrawPrimStrideData;
4853     drawPrimitive(iface, vertex_count, 0, 0, NULL);
4854     This->up_strided = NULL;
4855     return WINED3D_OK;
4856 }
4857
4858 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface,
4859         UINT vertex_count, const WineDirect3DVertexStridedData *DrawPrimStrideData,
4860         UINT NumVertices, const void *pIndexData, enum wined3d_format_id IndexDataFormat)
4861 {
4862     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4863     DWORD idxSize = (IndexDataFormat == WINED3DFMT_R32_UINT ? 4 : 2);
4864
4865     /* Mark the state dirty until we have nicer tracking
4866      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4867      * that value.
4868      */
4869     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4870     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4871     This->stateBlock->streamIsUP = TRUE;
4872     This->stateBlock->baseVertexIndex = 0;
4873     This->up_strided = DrawPrimStrideData;
4874     drawPrimitive(iface, vertex_count, 0 /* start_idx */, idxSize, pIndexData);
4875     This->up_strided = NULL;
4876     return WINED3D_OK;
4877 }
4878
4879 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
4880 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface,
4881         IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume)
4882 {
4883     WINED3DLOCKED_BOX src;
4884     WINED3DLOCKED_BOX dst;
4885     HRESULT hr;
4886
4887     TRACE("iface %p, src_volume %p, dst_volume %p.\n",
4888             iface, pSourceVolume, pDestinationVolume);
4889
4890     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
4891      * dirtification to improve loading performance.
4892      */
4893     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
4894     if(FAILED(hr)) return hr;
4895     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
4896     if(FAILED(hr)) {
4897     IWineD3DVolume_UnlockBox(pSourceVolume);
4898             return hr;
4899     }
4900
4901     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
4902
4903     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
4904     if(FAILED(hr)) {
4905         IWineD3DVolume_UnlockBox(pSourceVolume);
4906     } else {
4907         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
4908     }
4909     return hr;
4910 }
4911
4912 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice *iface,
4913         IWineD3DBaseTexture *src_texture, IWineD3DBaseTexture *dst_texture)
4914 {
4915     unsigned int level_count, i;
4916     WINED3DRESOURCETYPE type;
4917     HRESULT hr;
4918
4919     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
4920
4921     /* Verify that the source and destination textures are non-NULL. */
4922     if (!src_texture || !dst_texture)
4923     {
4924         WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
4925         return WINED3DERR_INVALIDCALL;
4926     }
4927
4928     if (src_texture == dst_texture)
4929     {
4930         WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
4931         return WINED3DERR_INVALIDCALL;
4932     }
4933
4934     /* Verify that the source and destination textures are the same type. */
4935     type = IWineD3DBaseTexture_GetType(src_texture);
4936     if (IWineD3DBaseTexture_GetType(dst_texture) != type)
4937     {
4938         WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
4939         return WINED3DERR_INVALIDCALL;
4940     }
4941
4942     /* Check that both textures have the identical numbers of levels. */
4943     level_count = IWineD3DBaseTexture_GetLevelCount(src_texture);
4944     if (IWineD3DBaseTexture_GetLevelCount(dst_texture) != level_count)
4945     {
4946         WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
4947         return WINED3DERR_INVALIDCALL;
4948     }
4949
4950     /* Make sure that the destination texture is loaded. */
4951     ((IWineD3DBaseTextureImpl *)dst_texture)->baseTexture.internal_preload(dst_texture, SRGB_RGB);
4952
4953     /* Update every surface level of the texture. */
4954     switch (type)
4955     {
4956         case WINED3DRTYPE_TEXTURE:
4957         {
4958             IWineD3DSurface *src_surface;
4959             IWineD3DSurface *dst_surface;
4960
4961             for (i = 0; i < level_count; ++i)
4962             {
4963                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)src_texture, i, &src_surface);
4964                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)dst_texture, i, &dst_surface);
4965                 hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4966                 IWineD3DSurface_Release(dst_surface);
4967                 IWineD3DSurface_Release(src_surface);
4968                 if (FAILED(hr))
4969                 {
4970                     WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
4971                     return hr;
4972                 }
4973             }
4974             break;
4975         }
4976
4977         case WINED3DRTYPE_CUBETEXTURE:
4978         {
4979             IWineD3DSurface *src_surface;
4980             IWineD3DSurface *dst_surface;
4981             WINED3DCUBEMAP_FACES face;
4982
4983             for (i = 0; i < level_count; ++i)
4984             {
4985                 /* Update each cube face. */
4986                 for (face = WINED3DCUBEMAP_FACE_POSITIVE_X; face <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++face)
4987                 {
4988                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)src_texture,
4989                             face, i, &src_surface);
4990                     if (FAILED(hr)) ERR("Failed to get src cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4991                     hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)dst_texture,
4992                             face, i, &dst_surface);
4993                     if (FAILED(hr)) ERR("Failed to get dst cube surface face %u, level %u, hr %#x.\n", face, i, hr);
4994                     hr = IWineD3DDevice_UpdateSurface(iface, src_surface, NULL, dst_surface, NULL);
4995                     IWineD3DSurface_Release(dst_surface);
4996                     IWineD3DSurface_Release(src_surface);
4997                     if (FAILED(hr))
4998                     {
4999                         WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr);
5000                         return hr;
5001                     }
5002                 }
5003             }
5004             break;
5005         }
5006
5007         case WINED3DRTYPE_VOLUMETEXTURE:
5008         {
5009             IWineD3DVolume *src_volume;
5010             IWineD3DVolume *dst_volume;
5011
5012             for (i = 0; i < level_count; ++i)
5013             {
5014                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)src_texture, i, &src_volume);
5015                 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)dst_texture, i, &dst_volume);
5016                 hr = IWineD3DDeviceImpl_UpdateVolume(iface, src_volume, dst_volume);
5017                 IWineD3DVolume_Release(dst_volume);
5018                 IWineD3DVolume_Release(src_volume);
5019                 if (FAILED(hr))
5020                 {
5021                     WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr);
5022                     return hr;
5023                 }
5024             }
5025             break;
5026         }
5027
5028         default:
5029             FIXME("Unsupported texture type %#x.\n", type);
5030             return WINED3DERR_INVALIDCALL;
5031     }
5032
5033     return WINED3D_OK;
5034 }
5035
5036 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,
5037         UINT swapchain_idx, IWineD3DSurface *dst_surface)
5038 {
5039     IWineD3DSwapChain *swapchain;
5040     HRESULT hr;
5041
5042     TRACE("iface %p, swapchain_idx %u, dst_surface %p.\n", iface, swapchain_idx, dst_surface);
5043
5044     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5045     if (FAILED(hr)) return hr;
5046
5047     hr = IWineD3DSwapChain_GetFrontBufferData(swapchain, dst_surface);
5048     IWineD3DSwapChain_Release(swapchain);
5049
5050     return hr;
5051 }
5052
5053 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5054     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5055     IWineD3DBaseTextureImpl *texture;
5056     DWORD i;
5057
5058     TRACE("(%p) : %p\n", This, pNumPasses);
5059
5060     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
5061     {
5062         if (This->stateBlock->state.sampler_states[i][WINED3DSAMP_MINFILTER] == WINED3DTEXF_NONE)
5063         {
5064             WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5065             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5066         }
5067         if (This->stateBlock->state.sampler_states[i][WINED3DSAMP_MAGFILTER] == WINED3DTEXF_NONE)
5068         {
5069             WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
5070             return WINED3DERR_UNSUPPORTEDTEXTUREFILTER;
5071         }
5072
5073         texture = (IWineD3DBaseTextureImpl *) This->stateBlock->textures[i];
5074         if (!texture || texture->resource.format->Flags & WINED3DFMT_FLAG_FILTERING) continue;
5075
5076         if (This->stateBlock->state.sampler_states[i][WINED3DSAMP_MAGFILTER] != WINED3DTEXF_POINT)
5077         {
5078             WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i);
5079             return E_FAIL;
5080         }
5081         if (This->stateBlock->state.sampler_states[i][WINED3DSAMP_MINFILTER] != WINED3DTEXF_POINT)
5082         {
5083             WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i);
5084             return E_FAIL;
5085         }
5086         if (This->stateBlock->state.sampler_states[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_NONE
5087                 && This->stateBlock->state.sampler_states[i][WINED3DSAMP_MIPFILTER] != WINED3DTEXF_POINT)
5088         {
5089             WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i);
5090             return E_FAIL;
5091         }
5092     }
5093
5094     /* return a sensible default */
5095     *pNumPasses = 1;
5096
5097     TRACE("returning D3D_OK\n");
5098     return WINED3D_OK;
5099 }
5100
5101 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5102 {
5103     int i;
5104
5105     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
5106     {
5107         IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5108         if (texture && (texture->resource.format->id == WINED3DFMT_P8_UINT
5109                 || texture->resource.format->id == WINED3DFMT_P8_UINT_A8_UNORM))
5110         {
5111             IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5112         }
5113     }
5114 }
5115
5116 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5117     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5118     int j;
5119     UINT NewSize;
5120     PALETTEENTRY **palettes;
5121
5122     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5123
5124     if (PaletteNumber >= MAX_PALETTES) {
5125         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5126         return WINED3DERR_INVALIDCALL;
5127     }
5128
5129     if (PaletteNumber >= This->NumberOfPalettes) {
5130         NewSize = This->NumberOfPalettes;
5131         do {
5132            NewSize *= 2;
5133         } while(PaletteNumber >= NewSize);
5134         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5135         if (!palettes) {
5136             ERR("Out of memory!\n");
5137             return E_OUTOFMEMORY;
5138         }
5139         This->palettes = palettes;
5140         This->NumberOfPalettes = NewSize;
5141     }
5142
5143     if (!This->palettes[PaletteNumber]) {
5144         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5145         if (!This->palettes[PaletteNumber]) {
5146             ERR("Out of memory!\n");
5147             return E_OUTOFMEMORY;
5148         }
5149     }
5150
5151     for (j = 0; j < 256; ++j) {
5152         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5153         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5154         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5155         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5156     }
5157     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5158     TRACE("(%p) : returning\n", This);
5159     return WINED3D_OK;
5160 }
5161
5162 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5164     int j;
5165     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5166     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5167         /* What happens in such situation isn't documented; Native seems to silently abort
5168            on such conditions. Return Invalid Call. */
5169         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5170         return WINED3DERR_INVALIDCALL;
5171     }
5172     for (j = 0; j < 256; ++j) {
5173         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5174         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5175         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5176         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5177     }
5178     TRACE("(%p) : returning\n", This);
5179     return WINED3D_OK;
5180 }
5181
5182 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5183     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5184     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5185     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5186        (tested with reference rasterizer). Return Invalid Call. */
5187     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5188         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5189         return WINED3DERR_INVALIDCALL;
5190     }
5191     /*TODO: stateblocks */
5192     if (This->currentPalette != PaletteNumber) {
5193         This->currentPalette = PaletteNumber;
5194         dirtify_p8_texture_samplers(This);
5195     }
5196     TRACE("(%p) : returning\n", This);
5197     return WINED3D_OK;
5198 }
5199
5200 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5201     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5202
5203     if (!PaletteNumber)
5204     {
5205         WARN("(%p) : returning Invalid Call\n", This);
5206         return WINED3DERR_INVALIDCALL;
5207     }
5208     /*TODO: stateblocks */
5209     *PaletteNumber = This->currentPalette;
5210     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5211     return WINED3D_OK;
5212 }
5213
5214 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5215     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5216     static BOOL warned;
5217     if (!warned)
5218     {
5219         FIXME("(%p) : stub\n", This);
5220         warned = TRUE;
5221     }
5222
5223     This->softwareVertexProcessing = bSoftware;
5224     return WINED3D_OK;
5225 }
5226
5227
5228 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5229     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5230     static BOOL warned;
5231     if (!warned)
5232     {
5233         FIXME("(%p) : stub\n", This);
5234         warned = TRUE;
5235     }
5236     return This->softwareVertexProcessing;
5237 }
5238
5239 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface,
5240         UINT swapchain_idx, WINED3DRASTER_STATUS *raster_status)
5241 {
5242     IWineD3DSwapChain *swapchain;
5243     HRESULT hr;
5244
5245     TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
5246             iface, swapchain_idx, raster_status);
5247
5248     hr = IWineD3DDeviceImpl_GetSwapChain(iface, swapchain_idx, &swapchain);
5249     if (FAILED(hr))
5250     {
5251         WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx, hr);
5252         return hr;
5253     }
5254
5255     hr = IWineD3DSwapChain_GetRasterStatus(swapchain, raster_status);
5256     IWineD3DSwapChain_Release(swapchain);
5257     if (FAILED(hr))
5258     {
5259         WARN("Failed to get raster status, hr %#x.\n", hr);
5260         return hr;
5261     }
5262
5263     return WINED3D_OK;
5264 }
5265
5266 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments)
5267 {
5268     static BOOL warned;
5269     if(nSegments != 0.0f) {
5270         if (!warned)
5271         {
5272             FIXME("iface %p, nSegments %.8e stub!\n", iface, nSegments);
5273             warned = TRUE;
5274         }
5275     }
5276     return WINED3D_OK;
5277 }
5278
5279 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface)
5280 {
5281     static BOOL warned;
5282     if (!warned)
5283     {
5284         FIXME("iface %p stub!\n", iface);
5285         warned = TRUE;
5286     }
5287     return 0.0f;
5288 }
5289
5290 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
5291         IWineD3DSurface *src_surface, const RECT *src_rect,
5292         IWineD3DSurface *dst_surface, const POINT *dst_point)
5293 {
5294     IWineD3DSurfaceImpl *src_impl = (IWineD3DSurfaceImpl *)src_surface;
5295     IWineD3DSurfaceImpl *dst_impl = (IWineD3DSurfaceImpl *)dst_surface;
5296     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5297     const struct wined3d_format *src_format;
5298     const struct wined3d_format *dst_format;
5299     const struct wined3d_gl_info *gl_info;
5300     struct wined3d_context *context;
5301     const unsigned char *data;
5302     UINT update_w, update_h;
5303     CONVERT_TYPES convert;
5304     UINT src_w, src_h;
5305     UINT dst_x, dst_y;
5306     DWORD sampler;
5307     struct wined3d_format format;
5308
5309     TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
5310             iface, src_surface, wine_dbgstr_rect(src_rect),
5311             dst_surface, wine_dbgstr_point(dst_point));
5312
5313     if (src_impl->resource.pool != WINED3DPOOL_SYSTEMMEM || dst_impl->resource.pool != WINED3DPOOL_DEFAULT)
5314     {
5315         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
5316                 src_surface, dst_surface);
5317         return WINED3DERR_INVALIDCALL;
5318     }
5319
5320     src_format = src_impl->resource.format;
5321     dst_format = dst_impl->resource.format;
5322
5323     if (src_format->id != dst_format->id)
5324     {
5325         WARN("Source and destination surfaces should have the same format.\n");
5326         return WINED3DERR_INVALIDCALL;
5327     }
5328
5329     dst_x = dst_point ? dst_point->x : 0;
5330     dst_y = dst_point ? dst_point->y : 0;
5331
5332     /* This call loads the OpenGL surface directly, instead of copying the
5333      * surface to the destination's sysmem copy. If surface conversion is
5334      * needed, use BltFast instead to copy in sysmem and use regular surface
5335      * loading. */
5336     d3dfmt_get_conv(dst_impl, FALSE, TRUE, &format, &convert);
5337     if (convert != NO_CONVERSION || format.convert)
5338         return IWineD3DSurface_BltFast(dst_surface, dst_x, dst_y, src_surface, src_rect, 0);
5339
5340     context = context_acquire(This, NULL);
5341     gl_info = context->gl_info;
5342
5343     ENTER_GL();
5344     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5345     checkGLcall("glActiveTextureARB");
5346     LEAVE_GL();
5347
5348     /* Make sure the surface is loaded and up to date */
5349     surface_internal_preload(dst_impl, SRGB_RGB);
5350     IWineD3DSurface_BindTexture(dst_surface, FALSE);
5351
5352     src_w = src_impl->currentDesc.Width;
5353     src_h = src_impl->currentDesc.Height;
5354     update_w = src_rect ? src_rect->right - src_rect->left : src_w;
5355     update_h = src_rect ? src_rect->bottom - src_rect->top : src_h;
5356
5357     data = IWineD3DSurface_GetData(src_surface);
5358     if (!data) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n");
5359
5360     ENTER_GL();
5361
5362     if (dst_format->Flags & WINED3DFMT_FLAG_COMPRESSED)
5363     {
5364         UINT row_length = wined3d_format_calculate_size(src_format, 1, update_w, 1);
5365         UINT row_count = (update_h + src_format->block_height - 1) / src_format->block_height;
5366         UINT src_pitch = wined3d_format_calculate_size(src_format, 1, src_w, 1);
5367
5368         if (src_rect)
5369         {
5370             data += (src_rect->top / src_format->block_height) * src_pitch;
5371             data += (src_rect->left / src_format->block_width) * src_format->block_byte_count;
5372         }
5373
5374         TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
5375                 "format %#x, image_size %#x, data %p.\n", dst_impl->texture_target, dst_impl->texture_level,
5376                 dst_x, dst_y, update_w, update_h, dst_format->glFormat, row_count * row_length, data);
5377
5378         if (row_length == src_pitch)
5379         {
5380             GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5381                     dst_x, dst_y, update_w, update_h, dst_format->glInternal, row_count * row_length, data));
5382         }
5383         else
5384         {
5385             UINT row, y;
5386
5387             /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
5388              * can't use the unpack row length like below. */
5389             for (row = 0, y = dst_y; row < row_count; ++row)
5390             {
5391                 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl->texture_target, dst_impl->texture_level,
5392                         dst_x, y, update_w, src_format->block_height, dst_format->glInternal, row_length, data));
5393                 y += src_format->block_height;
5394                 data += src_pitch;
5395             }
5396         }
5397         checkGLcall("glCompressedTexSubImage2DARB");
5398     }
5399     else
5400     {
5401         if (src_rect)
5402         {
5403             data += src_rect->top * src_w * src_format->byte_count;
5404             data += src_rect->left * src_format->byte_count;
5405         }
5406
5407         TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n",
5408                 dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5409                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5410
5411         glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w);
5412         glTexSubImage2D(dst_impl->texture_target, dst_impl->texture_level, dst_x, dst_y,
5413                 update_w, update_h, dst_format->glFormat, dst_format->glType, data);
5414         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
5415         checkGLcall("glTexSubImage2D");
5416     }
5417
5418     LEAVE_GL();
5419     context_release(context);
5420
5421     surface_modify_location(dst_impl, SFLAG_INTEXTURE, TRUE);
5422     sampler = This->rev_tex_unit_map[0];
5423     if (sampler != WINED3D_UNMAPPED_STAGE)
5424     {
5425         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5426     }
5427
5428     return WINED3D_OK;
5429 }
5430
5431 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5432     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5433     struct WineD3DRectPatch *patch;
5434     GLenum old_primitive_type;
5435     unsigned int i;
5436     struct list *e;
5437     BOOL found;
5438     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5439
5440     if(!(Handle || pRectPatchInfo)) {
5441         /* TODO: Write a test for the return value, thus the FIXME */
5442         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5443         return WINED3DERR_INVALIDCALL;
5444     }
5445
5446     if(Handle) {
5447         i = PATCHMAP_HASHFUNC(Handle);
5448         found = FALSE;
5449         LIST_FOR_EACH(e, &This->patches[i]) {
5450             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5451             if(patch->Handle == Handle) {
5452                 found = TRUE;
5453                 break;
5454             }
5455         }
5456
5457         if(!found) {
5458             TRACE("Patch does not exist. Creating a new one\n");
5459             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5460             patch->Handle = Handle;
5461             list_add_head(&This->patches[i], &patch->entry);
5462         } else {
5463             TRACE("Found existing patch %p\n", patch);
5464         }
5465     } else {
5466         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5467          * attributes we have to tesselate, read back, and draw. This needs a patch
5468          * management structure instance. Create one.
5469          *
5470          * A possible improvement is to check if a vertex shader is used, and if not directly
5471          * draw the patch.
5472          */
5473         FIXME("Drawing an uncached patch. This is slow\n");
5474         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5475     }
5476
5477     if (pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1]
5478             || pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3]
5479             || (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo))))
5480     {
5481         HRESULT hr;
5482         TRACE("Tesselation density or patch info changed, retesselating\n");
5483
5484         if(pRectPatchInfo) {
5485             patch->RectPatchInfo = *pRectPatchInfo;
5486         }
5487         patch->numSegs[0] = pNumSegs[0];
5488         patch->numSegs[1] = pNumSegs[1];
5489         patch->numSegs[2] = pNumSegs[2];
5490         patch->numSegs[3] = pNumSegs[3];
5491
5492         hr = tesselate_rectpatch(This, patch);
5493         if(FAILED(hr)) {
5494             WARN("Patch tesselation failed\n");
5495
5496             /* Do not release the handle to store the params of the patch */
5497             if(!Handle) {
5498                 HeapFree(GetProcessHeap(), 0, patch);
5499             }
5500             return hr;
5501         }
5502     }
5503
5504     This->currentPatch = patch;
5505     old_primitive_type = This->stateBlock->gl_primitive_type;
5506     This->stateBlock->gl_primitive_type = GL_TRIANGLES;
5507     IWineD3DDevice_DrawPrimitiveStrided(iface, patch->numSegs[0] * patch->numSegs[1] * 2 * 3, &patch->strided);
5508     This->stateBlock->gl_primitive_type = old_primitive_type;
5509     This->currentPatch = NULL;
5510
5511     /* Destroy uncached patches */
5512     if(!Handle) {
5513         HeapFree(GetProcessHeap(), 0, patch->mem);
5514         HeapFree(GetProcessHeap(), 0, patch);
5515     }
5516     return WINED3D_OK;
5517 }
5518
5519 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface,
5520         UINT handle, const float *segment_count, const WINED3DTRIPATCH_INFO *patch_info)
5521 {
5522     FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5523             iface, handle, segment_count, patch_info);
5524
5525     return WINED3D_OK;
5526 }
5527
5528 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5529     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5530     int i;
5531     struct WineD3DRectPatch *patch;
5532     struct list *e;
5533     TRACE("(%p) Handle(%d)\n", This, Handle);
5534
5535     i = PATCHMAP_HASHFUNC(Handle);
5536     LIST_FOR_EACH(e, &This->patches[i]) {
5537         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5538         if(patch->Handle == Handle) {
5539             TRACE("Deleting patch %p\n", patch);
5540             list_remove(&patch->entry);
5541             HeapFree(GetProcessHeap(), 0, patch->mem);
5542             HeapFree(GetProcessHeap(), 0, patch);
5543             return WINED3D_OK;
5544         }
5545     }
5546
5547     /* TODO: Write a test for the return value */
5548     FIXME("Attempt to destroy nonexistent patch\n");
5549     return WINED3DERR_INVALIDCALL;
5550 }
5551
5552 /* Do not call while under the GL lock. */
5553 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface,
5554         IWineD3DSurface *surface, const RECT *rect, const WINED3DCOLORVALUE *color)
5555 {
5556     IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)surface;
5557
5558     TRACE("iface %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
5559             iface, surface, wine_dbgstr_rect(rect),
5560             color->r, color->g, color->b, color->a);
5561
5562     if (s->resource.pool != WINED3DPOOL_DEFAULT && s->resource.pool != WINED3DPOOL_SYSTEMMEM)
5563     {
5564         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5565         return WINED3DERR_INVALIDCALL;
5566     }
5567
5568     return surface_color_fill(s, rect, color);
5569 }
5570
5571 /* Do not call while under the GL lock. */
5572 static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice *iface,
5573         IWineD3DRendertargetView *rendertarget_view, const WINED3DCOLORVALUE *color)
5574 {
5575     IWineD3DResource *resource;
5576     HRESULT hr;
5577
5578     hr = IWineD3DRendertargetView_GetResource(rendertarget_view, &resource);
5579     if (FAILED(hr))
5580     {
5581         ERR("Failed to get resource, hr %#x\n", hr);
5582         return;
5583     }
5584
5585     if (IWineD3DResource_GetType(resource) != WINED3DRTYPE_SURFACE)
5586     {
5587         FIXME("Only supported on surface resources\n");
5588         IWineD3DResource_Release(resource);
5589         return;
5590     }
5591
5592     hr = surface_color_fill((IWineD3DSurfaceImpl *)resource, NULL, color);
5593     if (FAILED(hr)) ERR("Color fill failed, hr %#x.\n", hr);
5594
5595     IWineD3DResource_Release(resource);
5596 }
5597
5598 /* rendertarget and depth stencil functions */
5599 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice *iface,
5600         DWORD render_target_idx, IWineD3DSurface **render_target)
5601 {
5602     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5603
5604     TRACE("iface %p, render_target_idx %u, render_target %p.\n",
5605             iface, render_target_idx, render_target);
5606
5607     if (render_target_idx >= device->adapter->gl_info.limits.buffers)
5608     {
5609         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
5610         return WINED3DERR_INVALIDCALL;
5611     }
5612
5613     *render_target = (IWineD3DSurface *)device->render_targets[render_target_idx];
5614     if (*render_target) IWineD3DSurface_AddRef(*render_target);
5615
5616     TRACE("Returning render target %p.\n", *render_target);
5617
5618     return WINED3D_OK;
5619 }
5620
5621 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface,
5622         IWineD3DSurface *front, IWineD3DSurface *back)
5623 {
5624     IWineD3DSurfaceImpl *front_impl = (IWineD3DSurfaceImpl *)front;
5625     IWineD3DSurfaceImpl *back_impl = (IWineD3DSurfaceImpl *)back;
5626     IWineD3DSwapChainImpl *swapchain;
5627     HRESULT hr;
5628
5629     TRACE("iface %p, front %p, back %p.\n", iface, front, back);
5630
5631     if (FAILED(hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&swapchain)))
5632     {
5633         ERR("Failed to get the swapchain, hr %#x.\n", hr);
5634         return hr;
5635     }
5636
5637     if (front_impl && !(front_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5638     {
5639         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5640         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5641         return WINED3DERR_INVALIDCALL;
5642     }
5643
5644     if (back_impl)
5645     {
5646         if (!(back_impl->resource.usage & WINED3DUSAGE_RENDERTARGET))
5647         {
5648             ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage.\n");
5649             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5650             return WINED3DERR_INVALIDCALL;
5651         }
5652
5653         if (!swapchain->back_buffers)
5654         {
5655             swapchain->back_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*swapchain->back_buffers));
5656             if (!swapchain->back_buffers)
5657             {
5658                 ERR("Failed to allocate back buffer array memory.\n");
5659                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5660                 return E_OUTOFMEMORY;
5661             }
5662         }
5663     }
5664
5665     if (swapchain->front_buffer != front_impl)
5666     {
5667         TRACE("Changing the front buffer from %p to %p.\n", swapchain->front_buffer, front_impl);
5668
5669         if (swapchain->front_buffer)
5670             surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_NONE, NULL);
5671         swapchain->front_buffer = front_impl;
5672
5673         if (front_impl)
5674             surface_set_container(front_impl, WINED3D_CONTAINER_SWAPCHAIN, (IWineD3DBase *)swapchain);
5675     }
5676
5677     if (swapchain->back_buffers[0] != back_impl)
5678     {
5679         TRACE("Changing the back buffer from %p to %p.\n", swapchain->back_buffers[0], back_impl);
5680
5681         if (swapchain->back_buffers[0])
5682             surface_set_container(swapchain->back_buffers[0], WINED3D_CONTAINER_NONE, NULL);
5683         swapchain->back_buffers[0] = back_impl;
5684
5685         if (back_impl)
5686         {
5687             swapchain->presentParms.BackBufferWidth = back_impl->currentDesc.Width;
5688             swapchain->presentParms.BackBufferHeight = back_impl->currentDesc.Height;
5689             swapchain->presentParms.BackBufferFormat = back_impl->resource.format->id;
5690             swapchain->presentParms.BackBufferCount = 1;
5691
5692             surface_set_container(back_impl, WINED3D_CONTAINER_SWAPCHAIN, (IWineD3DBase *)swapchain);
5693         }
5694         else
5695         {
5696             swapchain->presentParms.BackBufferCount = 0;
5697             HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
5698             swapchain->back_buffers = NULL;
5699         }
5700     }
5701
5702     IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5703     return WINED3D_OK;
5704 }
5705
5706 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface **depth_stencil)
5707 {
5708     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5709
5710     TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
5711
5712     *depth_stencil = (IWineD3DSurface *)device->depth_stencil;
5713     TRACE("Returning depth/stencil surface %p.\n", *depth_stencil);
5714     if (!*depth_stencil) return WINED3DERR_NOTFOUND;
5715     IWineD3DSurface_AddRef(*depth_stencil);
5716
5717     return WINED3D_OK;
5718 }
5719
5720 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
5721         DWORD render_target_idx, IWineD3DSurface *render_target, BOOL set_viewport)
5722 {
5723     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)iface;
5724     IWineD3DSurfaceImpl *prev;
5725
5726     TRACE("iface %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
5727             iface, render_target_idx, render_target, set_viewport);
5728
5729     if (render_target_idx >= device->adapter->gl_info.limits.buffers)
5730     {
5731         WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
5732         return WINED3DERR_INVALIDCALL;
5733     }
5734
5735     prev = device->render_targets[render_target_idx];
5736     if (render_target == (IWineD3DSurface *)prev)
5737     {
5738         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5739         return WINED3D_OK;
5740     }
5741
5742     /* Render target 0 can't be set to NULL. */
5743     if (!render_target && !render_target_idx)
5744     {
5745         WARN("Trying to set render target 0 to NULL.\n");
5746         return WINED3DERR_INVALIDCALL;
5747     }
5748
5749     if (render_target && !(((IWineD3DSurfaceImpl *)render_target)->resource.usage & WINED3DUSAGE_RENDERTARGET))
5750     {
5751         FIXME("Surface %p doesn't have render target usage.\n", render_target);
5752         return WINED3DERR_INVALIDCALL;
5753     }
5754
5755     if (render_target) IWineD3DSurface_AddRef(render_target);
5756     device->render_targets[render_target_idx] = (IWineD3DSurfaceImpl *)render_target;
5757     /* Release after the assignment, to prevent device_resource_released()
5758      * from seeing the surface as still in use. */
5759     if (prev) IWineD3DSurface_Release((IWineD3DSurface *)prev);
5760
5761     /* Render target 0 is special. */
5762     if (!render_target_idx && set_viewport)
5763     {
5764         /* Set the viewport and scissor rectangles, if requested. Tests show
5765          * that stateblock recording is ignored, the change goes directly
5766          * into the primary stateblock. */
5767         device->stateBlock->state.viewport.Height = device->render_targets[0]->currentDesc.Height;
5768         device->stateBlock->state.viewport.Width  = device->render_targets[0]->currentDesc.Width;
5769         device->stateBlock->state.viewport.X      = 0;
5770         device->stateBlock->state.viewport.Y      = 0;
5771         device->stateBlock->state.viewport.MaxZ   = 1.0f;
5772         device->stateBlock->state.viewport.MinZ   = 0.0f;
5773         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_VIEWPORT);
5774
5775         device->stateBlock->state.scissor_rect.top = 0;
5776         device->stateBlock->state.scissor_rect.left = 0;
5777         device->stateBlock->state.scissor_rect.right = device->stateBlock->state.viewport.Width;
5778         device->stateBlock->state.scissor_rect.bottom = device->stateBlock->state.viewport.Height;
5779         IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SCISSORRECT);
5780     }
5781
5782     return WINED3D_OK;
5783 }
5784
5785 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil)
5786 {
5787     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5788     IWineD3DSurfaceImpl *tmp;
5789
5790     TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This, depth_stencil, This->depth_stencil);
5791
5792     if (This->depth_stencil == (IWineD3DSurfaceImpl *)depth_stencil)
5793     {
5794         TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5795         return WINED3D_OK;
5796     }
5797
5798     if (This->depth_stencil)
5799     {
5800         if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5801                 || This->depth_stencil->Flags & SFLAG_DISCARD)
5802         {
5803             surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED,
5804                     This->depth_stencil->currentDesc.Width,
5805                     This->depth_stencil->currentDesc.Height);
5806             if (This->depth_stencil == This->onscreen_depth_stencil)
5807             {
5808                 IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
5809                 This->onscreen_depth_stencil = NULL;
5810             }
5811         }
5812     }
5813
5814     tmp = This->depth_stencil;
5815     This->depth_stencil = (IWineD3DSurfaceImpl *)depth_stencil;
5816     if (This->depth_stencil) IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil);
5817     if (tmp) IWineD3DSurface_Release((IWineD3DSurface *)tmp);
5818
5819     if ((!tmp && depth_stencil) || (!depth_stencil && tmp))
5820     {
5821         /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5822         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5823         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5824         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5825     }
5826
5827     return WINED3D_OK;
5828 }
5829
5830 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice *iface,
5831         UINT XHotSpot, UINT YHotSpot, IWineD3DSurface *cursor_image)
5832 {
5833     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5834     IWineD3DSurfaceImpl *s = (IWineD3DSurfaceImpl *)cursor_image;
5835     WINED3DLOCKED_RECT lockedRect;
5836
5837     TRACE("iface %p, hotspot_x %u, hotspot_y %u, cursor_image %p.\n",
5838             iface, XHotSpot, YHotSpot, cursor_image);
5839
5840     /* some basic validation checks */
5841     if (This->cursorTexture)
5842     {
5843         struct wined3d_context *context = context_acquire(This, NULL);
5844         ENTER_GL();
5845         glDeleteTextures(1, &This->cursorTexture);
5846         LEAVE_GL();
5847         context_release(context);
5848         This->cursorTexture = 0;
5849     }
5850
5851     if ((s->currentDesc.Width == 32) && (s->currentDesc.Height == 32))
5852         This->haveHardwareCursor = TRUE;
5853     else
5854         This->haveHardwareCursor = FALSE;
5855
5856     if (cursor_image)
5857     {
5858         WINED3DLOCKED_RECT rect;
5859
5860         /* MSDN: Cursor must be A8R8G8B8 */
5861         if (s->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM)
5862         {
5863             WARN("surface %p has an invalid format.\n", cursor_image);
5864             return WINED3DERR_INVALIDCALL;
5865         }
5866
5867         /* MSDN: Cursor must be smaller than the display mode */
5868         if (s->currentDesc.Width > This->ddraw_width
5869                 || s->currentDesc.Height > This->ddraw_height)
5870         {
5871             WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
5872                     s, s->currentDesc.Width, s->currentDesc.Height, This->ddraw_width, This->ddraw_height);
5873             return WINED3DERR_INVALIDCALL;
5874         }
5875
5876         if (!This->haveHardwareCursor) {
5877             /* TODO: MSDN: Cursor sizes must be a power of 2 */
5878
5879             /* Do not store the surface's pointer because the application may
5880              * release it after setting the cursor image. Windows doesn't
5881              * addref the set surface, so we can't do this either without
5882              * creating circular refcount dependencies. Copy out the gl texture
5883              * instead.
5884              */
5885             This->cursorWidth = s->currentDesc.Width;
5886             This->cursorHeight = s->currentDesc.Height;
5887             if (SUCCEEDED(IWineD3DSurface_LockRect(cursor_image, &rect, NULL, WINED3DLOCK_READONLY)))
5888             {
5889                 const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
5890                 const struct wined3d_format *format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
5891                 struct wined3d_context *context;
5892                 char *mem, *bits = rect.pBits;
5893                 GLint intfmt = format->glInternal;
5894                 GLint gl_format = format->glFormat;
5895                 GLint type = format->glType;
5896                 INT height = This->cursorHeight;
5897                 INT width = This->cursorWidth;
5898                 INT bpp = format->byte_count;
5899                 DWORD sampler;
5900                 INT i;
5901
5902                 /* Reformat the texture memory (pitch and width can be
5903                  * different) */
5904                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
5905                 for(i = 0; i < height; i++)
5906                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
5907                 IWineD3DSurface_UnlockRect(cursor_image);
5908
5909                 context = context_acquire(This, NULL);
5910
5911                 ENTER_GL();
5912
5913                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
5914                 {
5915                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
5916                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5917                 }
5918
5919                 /* Make sure that a proper texture unit is selected */
5920                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5921                 checkGLcall("glActiveTextureARB");
5922                 sampler = This->rev_tex_unit_map[0];
5923                 if (sampler != WINED3D_UNMAPPED_STAGE)
5924                 {
5925                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler));
5926                 }
5927                 /* Create a new cursor texture */
5928                 glGenTextures(1, &This->cursorTexture);
5929                 checkGLcall("glGenTextures");
5930                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
5931                 checkGLcall("glBindTexture");
5932                 /* Copy the bitmap memory into the cursor texture */
5933                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, gl_format, type, mem);
5934                 HeapFree(GetProcessHeap(), 0, mem);
5935                 checkGLcall("glTexImage2D");
5936
5937                 if (gl_info->supported[APPLE_CLIENT_STORAGE])
5938                 {
5939                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
5940                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
5941                 }
5942
5943                 LEAVE_GL();
5944
5945                 context_release(context);
5946             }
5947             else
5948             {
5949                 FIXME("A cursor texture was not returned.\n");
5950                 This->cursorTexture = 0;
5951             }
5952         }
5953         else
5954         {
5955             /* Draw a hardware cursor */
5956             ICONINFO cursorInfo;
5957             HCURSOR cursor;
5958             /* Create and clear maskBits because it is not needed for
5959              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
5960              * chunks. */
5961             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5962                     (s->currentDesc.Width * s->currentDesc.Height / 8));
5963             IWineD3DSurface_LockRect(cursor_image, &lockedRect, NULL,
5964                     WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY);
5965             TRACE("width: %u height: %u.\n", s->currentDesc.Width, s->currentDesc.Height);
5966
5967             cursorInfo.fIcon = FALSE;
5968             cursorInfo.xHotspot = XHotSpot;
5969             cursorInfo.yHotspot = YHotSpot;
5970             cursorInfo.hbmMask = CreateBitmap(s->currentDesc.Width, s->currentDesc.Height, 1, 1, maskBits);
5971             cursorInfo.hbmColor = CreateBitmap(s->currentDesc.Width, s->currentDesc.Height, 1, 32, lockedRect.pBits);
5972             IWineD3DSurface_UnlockRect(cursor_image);
5973             /* Create our cursor and clean up. */
5974             cursor = CreateIconIndirect(&cursorInfo);
5975             SetCursor(cursor);
5976             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
5977             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
5978             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
5979             This->hardwareCursor = cursor;
5980             HeapFree(GetProcessHeap(), 0, maskBits);
5981         }
5982     }
5983
5984     This->xHotSpot = XHotSpot;
5985     This->yHotSpot = YHotSpot;
5986     return WINED3D_OK;
5987 }
5988
5989 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5990     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5991     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5992
5993     This->xScreenSpace = XScreenSpace;
5994     This->yScreenSpace = YScreenSpace;
5995
5996     return;
5997
5998 }
5999
6000 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6001     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6002     BOOL oldVisible = This->bCursorVisible;
6003     POINT pt;
6004
6005     TRACE("(%p) : visible(%d)\n", This, bShow);
6006
6007     /*
6008      * When ShowCursor is first called it should make the cursor appear at the OS's last
6009      * known cursor position.  Because of this, some applications just repetitively call
6010      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6011      */
6012     GetCursorPos(&pt);
6013     This->xScreenSpace = pt.x;
6014     This->yScreenSpace = pt.y;
6015
6016     if (This->haveHardwareCursor) {
6017         This->bCursorVisible = bShow;
6018         if (bShow)
6019             SetCursor(This->hardwareCursor);
6020         else
6021             SetCursor(NULL);
6022     }
6023     else
6024     {
6025         if (This->cursorTexture)
6026             This->bCursorVisible = bShow;
6027     }
6028
6029     return oldVisible;
6030 }
6031
6032 static HRESULT WINAPI evict_managed_resource(IWineD3DResource *resource, void *data) {
6033     TRACE("checking resource %p for eviction\n", resource);
6034     if(((IWineD3DResourceImpl *) resource)->resource.pool == WINED3DPOOL_MANAGED) {
6035         TRACE("Evicting %p\n", resource);
6036         IWineD3DResource_UnLoad(resource);
6037     }
6038     IWineD3DResource_Release(resource);
6039     return S_OK;
6040 }
6041
6042 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice *iface)
6043 {
6044     TRACE("iface %p.\n", iface);
6045
6046     IWineD3DDevice_EnumResources(iface, evict_managed_resource, NULL);
6047     /* Invalidate stream sources, the buffer(s) may have been evicted. */
6048     IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)iface, STATE_STREAMSRC);
6049
6050     return WINED3D_OK;
6051 }
6052
6053 static HRESULT updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
6054 {
6055     IWineD3DDeviceImpl *device = surface->resource.device;
6056     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6057
6058     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6059     if(surface->Flags & SFLAG_DIBSECTION) {
6060         /* Release the DC */
6061         SelectObject(surface->hDC, surface->dib.holdbitmap);
6062         DeleteDC(surface->hDC);
6063         /* Release the DIB section */
6064         DeleteObject(surface->dib.DIBsection);
6065         surface->dib.bitmap_data = NULL;
6066         surface->resource.allocatedMemory = NULL;
6067         surface->Flags &= ~SFLAG_DIBSECTION;
6068     }
6069     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6070     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6071     if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
6072             || gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
6073     {
6074         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6075         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6076     } else {
6077         surface->pow2Width = surface->pow2Height = 1;
6078         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6079         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6080     }
6081
6082     if (surface->texture_name)
6083     {
6084         struct wined3d_context *context = context_acquire(device, NULL);
6085         ENTER_GL();
6086         glDeleteTextures(1, &surface->texture_name);
6087         LEAVE_GL();
6088         context_release(context);
6089         surface->texture_name = 0;
6090         surface->Flags &= ~SFLAG_CLIENT;
6091     }
6092     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6093        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6094         surface->Flags |= SFLAG_NONPOW2;
6095     } else  {
6096         surface->Flags &= ~SFLAG_NONPOW2;
6097     }
6098     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
6099     surface->resource.allocatedMemory = NULL;
6100     surface->resource.heapMemory = NULL;
6101     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6102
6103     /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6104      * to a FBO */
6105     if (!surface_init_sysmem(surface))
6106     {
6107         return E_OUTOFMEMORY;
6108     }
6109     return WINED3D_OK;
6110 }
6111
6112 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6113     TRACE("Unloading resource %p\n", resource);
6114     IWineD3DResource_UnLoad(resource);
6115     IWineD3DResource_Release(resource);
6116     return S_OK;
6117 }
6118
6119 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
6120 {
6121     UINT i, count;
6122     WINED3DDISPLAYMODE m;
6123     HRESULT hr;
6124
6125     /* All Windowed modes are supported, as is leaving the current mode */
6126     if(pp->Windowed) return TRUE;
6127     if(!pp->BackBufferWidth) return TRUE;
6128     if(!pp->BackBufferHeight) return TRUE;
6129
6130     count = IWineD3D_GetAdapterModeCount(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN);
6131     for(i = 0; i < count; i++) {
6132         memset(&m, 0, sizeof(m));
6133         hr = IWineD3D_EnumAdapterModes(This->wined3d, This->adapter->ordinal, WINED3DFMT_UNKNOWN, i, &m);
6134         if(FAILED(hr)) {
6135             ERR("EnumAdapterModes failed\n");
6136         }
6137         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
6138             /* Mode found, it is supported */
6139             return TRUE;
6140         }
6141     }
6142     /* Mode not found -> not supported */
6143     return FALSE;
6144 }
6145
6146 /* Do not call while under the GL lock. */
6147 static void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6148 {
6149     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6150     const struct wined3d_gl_info *gl_info;
6151     struct wined3d_context *context;
6152     IWineD3DBaseShaderImpl *shader;
6153
6154     context = context_acquire(This, NULL);
6155     gl_info = context->gl_info;
6156
6157     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6158     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6159         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6160     }
6161
6162     ENTER_GL();
6163     if(This->depth_blt_texture) {
6164         glDeleteTextures(1, &This->depth_blt_texture);
6165         This->depth_blt_texture = 0;
6166     }
6167     if (This->depth_blt_rb) {
6168         gl_info->fbo_ops.glDeleteRenderbuffers(1, &This->depth_blt_rb);
6169         This->depth_blt_rb = 0;
6170         This->depth_blt_rb_w = 0;
6171         This->depth_blt_rb_h = 0;
6172     }
6173     LEAVE_GL();
6174
6175     This->blitter->free_private(iface);
6176     This->frag_pipe->free_private(iface);
6177     This->shader_backend->shader_free_private(iface);
6178     destroy_dummy_textures(This, gl_info);
6179
6180     context_release(context);
6181
6182     while (This->numContexts)
6183     {
6184         context_destroy(This, This->contexts[0]);
6185     }
6186     HeapFree(GetProcessHeap(), 0, swapchain->context);
6187     swapchain->context = NULL;
6188     swapchain->num_contexts = 0;
6189 }
6190
6191 /* Do not call while under the GL lock. */
6192 static HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChainImpl *swapchain)
6193 {
6194     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6195     struct wined3d_context *context;
6196     HRESULT hr;
6197     IWineD3DSurfaceImpl *target;
6198
6199     /* Recreate the primary swapchain's context */
6200     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
6201     if (!swapchain->context)
6202     {
6203         ERR("Failed to allocate memory for swapchain context array.\n");
6204         return E_OUTOFMEMORY;
6205     }
6206
6207     target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
6208     if (!(context = context_create(swapchain, target, swapchain->ds_format)))
6209     {
6210         WARN("Failed to create context.\n");
6211         HeapFree(GetProcessHeap(), 0, swapchain->context);
6212         return E_FAIL;
6213     }
6214
6215     swapchain->context[0] = context;
6216     swapchain->num_contexts = 1;
6217     create_dummy_textures(This);
6218     context_release(context);
6219
6220     hr = This->shader_backend->shader_alloc_private(iface);
6221     if (FAILED(hr))
6222     {
6223         ERR("Failed to allocate shader private data, hr %#x.\n", hr);
6224         goto err;
6225     }
6226
6227     hr = This->frag_pipe->alloc_private(iface);
6228     if (FAILED(hr))
6229     {
6230         ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr);
6231         This->shader_backend->shader_free_private(iface);
6232         goto err;
6233     }
6234
6235     hr = This->blitter->alloc_private(iface);
6236     if (FAILED(hr))
6237     {
6238         ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
6239         This->frag_pipe->free_private(iface);
6240         This->shader_backend->shader_free_private(iface);
6241         goto err;
6242     }
6243
6244     return WINED3D_OK;
6245
6246 err:
6247     context_acquire(This, NULL);
6248     destroy_dummy_textures(This, context->gl_info);
6249     context_release(context);
6250     context_destroy(This, context);
6251     HeapFree(GetProcessHeap(), 0, swapchain->context);
6252     swapchain->num_contexts = 0;
6253     return hr;
6254 }
6255
6256 /* Do not call while under the GL lock. */
6257 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice *iface,
6258         WINED3DPRESENT_PARAMETERS *pPresentationParameters)
6259 {
6260     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6261     IWineD3DSwapChainImpl *swapchain;
6262     HRESULT hr;
6263     BOOL DisplayModeChanged = FALSE;
6264     WINED3DDISPLAYMODE mode;
6265     TRACE("(%p)\n", This);
6266
6267     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6268     if(FAILED(hr)) {
6269         ERR("Failed to get the first implicit swapchain\n");
6270         return hr;
6271     }
6272
6273     if(!is_display_mode_supported(This, pPresentationParameters)) {
6274         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6275         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
6276              pPresentationParameters->BackBufferHeight);
6277         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6278         return WINED3DERR_INVALIDCALL;
6279     }
6280
6281     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6282      * on an existing gl context, so there's no real need for recreation.
6283      *
6284      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6285      *
6286      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6287      */
6288     TRACE("New params:\n");
6289     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6290     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6291     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6292     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6293     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6294     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6295     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6296     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6297     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6298     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6299     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6300     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6301     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6302
6303     /* No special treatment of these parameters. Just store them */
6304     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6305     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6306     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6307     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6308
6309     /* What to do about these? */
6310     if (pPresentationParameters->BackBufferCount
6311             && pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount)
6312         ERR("Cannot change the back buffer count yet\n");
6313
6314     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6315         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6316         ERR("Cannot change the back buffer format yet\n");
6317     }
6318
6319     if (pPresentationParameters->hDeviceWindow
6320             && pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow)
6321         ERR("Cannot change the device window yet\n");
6322
6323     if (pPresentationParameters->EnableAutoDepthStencil && !This->auto_depth_stencil)
6324     {
6325         HRESULT hrc;
6326
6327         TRACE("Creating the depth stencil buffer\n");
6328
6329         hrc = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent,
6330                 pPresentationParameters->BackBufferWidth,
6331                 pPresentationParameters->BackBufferHeight,
6332                 pPresentationParameters->AutoDepthStencilFormat,
6333                 pPresentationParameters->MultiSampleType,
6334                 pPresentationParameters->MultiSampleQuality,
6335                 FALSE,
6336                 (IWineD3DSurface **)&This->auto_depth_stencil);
6337
6338         if (FAILED(hrc)) {
6339             ERR("Failed to create the depth stencil buffer\n");
6340             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6341             return WINED3DERR_INVALIDCALL;
6342         }
6343     }
6344
6345     if (This->onscreen_depth_stencil)
6346     {
6347         IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil);
6348         This->onscreen_depth_stencil = NULL;
6349     }
6350
6351     /* Reset the depth stencil */
6352     if (pPresentationParameters->EnableAutoDepthStencil)
6353         IWineD3DDevice_SetDepthStencilSurface(iface, (IWineD3DSurface *)This->auto_depth_stencil);
6354     else
6355         IWineD3DDevice_SetDepthStencilSurface(iface, NULL);
6356
6357     TRACE("Resetting stateblock\n");
6358     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock);
6359     IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
6360
6361     delete_opengl_contexts(iface, swapchain);
6362
6363     if(pPresentationParameters->Windowed) {
6364         mode.Width = swapchain->orig_width;
6365         mode.Height = swapchain->orig_height;
6366         mode.RefreshRate = 0;
6367         mode.Format = swapchain->presentParms.BackBufferFormat;
6368     } else {
6369         mode.Width = pPresentationParameters->BackBufferWidth;
6370         mode.Height = pPresentationParameters->BackBufferHeight;
6371         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6372         mode.Format = swapchain->presentParms.BackBufferFormat;
6373     }
6374
6375     /* Should Width == 800 && Height == 0 set 800x600? */
6376     if (pPresentationParameters->BackBufferWidth && pPresentationParameters->BackBufferHeight
6377             && (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth
6378             || pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6379     {
6380         UINT i;
6381
6382         if(!pPresentationParameters->Windowed) {
6383             DisplayModeChanged = TRUE;
6384         }
6385         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6386         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6387
6388         hr = updateSurfaceDesc(swapchain->front_buffer, pPresentationParameters);
6389         if(FAILED(hr))
6390         {
6391             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6392             return hr;
6393         }
6394
6395         for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i)
6396         {
6397             hr = updateSurfaceDesc(swapchain->back_buffers[i], pPresentationParameters);
6398             if(FAILED(hr))
6399             {
6400                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6401                 return hr;
6402             }
6403         }
6404         if (This->auto_depth_stencil)
6405         {
6406             hr = updateSurfaceDesc(This->auto_depth_stencil, pPresentationParameters);
6407             if(FAILED(hr))
6408             {
6409                 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6410                 return hr;
6411             }
6412         }
6413     }
6414
6415     if (!pPresentationParameters->Windowed != !swapchain->presentParms.Windowed
6416             || DisplayModeChanged)
6417     {
6418         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6419
6420         if (!pPresentationParameters->Windowed)
6421         {
6422             if(swapchain->presentParms.Windowed) {
6423                 /* switch from windowed to fs */
6424                 swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6425                         pPresentationParameters->BackBufferHeight);
6426             } else {
6427                 /* Fullscreen -> fullscreen mode change */
6428                 MoveWindow(swapchain->device_window, 0, 0,
6429                            pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
6430                            TRUE);
6431             }
6432         }
6433         else if (!swapchain->presentParms.Windowed)
6434         {
6435             /* Fullscreen -> windowed switch */
6436             swapchain_restore_fullscreen_window(swapchain);
6437         }
6438         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6439     } else if(!pPresentationParameters->Windowed) {
6440         DWORD style = This->style, exStyle = This->exStyle;
6441         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6442          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6443          * Reset to clear up their mess. Guild Wars also loses the device during that.
6444          */
6445         This->style = 0;
6446         This->exStyle = 0;
6447         swapchain_setup_fullscreen_window(swapchain, pPresentationParameters->BackBufferWidth,
6448                 pPresentationParameters->BackBufferHeight);
6449         This->style = style;
6450         This->exStyle = exStyle;
6451     }
6452
6453     /* Note: No parent needed for initial internal stateblock */
6454     hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock);
6455     if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6456     else TRACE("Created stateblock %p\n", This->stateBlock);
6457     This->updateStateBlock = This->stateBlock;
6458     IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock);
6459
6460     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
6461     if(FAILED(hr)) {
6462         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
6463     }
6464
6465     if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
6466     {
6467         RECT client_rect;
6468         GetClientRect(swapchain->win_handle, &client_rect);
6469
6470         if(!swapchain->presentParms.BackBufferCount)
6471         {
6472             TRACE("Single buffered rendering\n");
6473             swapchain->render_to_fbo = FALSE;
6474         }
6475         else if(swapchain->presentParms.BackBufferWidth  != client_rect.right  ||
6476                 swapchain->presentParms.BackBufferHeight != client_rect.bottom )
6477         {
6478             TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6479                     swapchain->presentParms.BackBufferWidth,
6480                     swapchain->presentParms.BackBufferHeight,
6481                     client_rect.right, client_rect.bottom);
6482             swapchain->render_to_fbo = TRUE;
6483         }
6484         else
6485         {
6486             TRACE("Rendering directly to GL_BACK\n");
6487             swapchain->render_to_fbo = FALSE;
6488         }
6489     }
6490
6491     hr = create_primary_opengl_context(iface, swapchain);
6492     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6493
6494     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6495      * first use
6496      */
6497     return hr;
6498 }
6499
6500 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL enable_dialogs)
6501 {
6502     TRACE("iface %p, enable_dialogs %#x.\n", iface, enable_dialogs);
6503
6504     if (!enable_dialogs) FIXME("Dialogs cannot be disabled yet.\n");
6505
6506     return WINED3D_OK;
6507 }
6508
6509
6510 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6511     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6512     TRACE("(%p) : pParameters %p\n", This, pParameters);
6513
6514     *pParameters = This->createParms;
6515     return WINED3D_OK;
6516 }
6517
6518 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6519     IWineD3DSwapChain *swapchain;
6520
6521     TRACE("Relaying  to swapchain\n");
6522
6523     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6524         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, pRamp);
6525         IWineD3DSwapChain_Release(swapchain);
6526     }
6527 }
6528
6529 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6530     IWineD3DSwapChain *swapchain;
6531
6532     TRACE("Relaying  to swapchain\n");
6533
6534     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
6535         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6536         IWineD3DSwapChain_Release(swapchain);
6537     }
6538 }
6539
6540
6541 /** ********************************************************
6542 *   Notification functions
6543 ** ********************************************************/
6544 /** This function must be called in the release of a resource when ref == 0,
6545 * the contents of resource must still be correct,
6546 * any handles to other resource held by the caller must be closed
6547 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6548  *****************************************************/
6549 void device_resource_add(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6550 {
6551     TRACE("(%p) : Adding resource %p\n", This, resource);
6552
6553     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6554 }
6555
6556 static void device_resource_remove(IWineD3DDeviceImpl *This, IWineD3DResource *resource)
6557 {
6558     TRACE("(%p) : Removing resource %p\n", This, resource);
6559
6560     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6561 }
6562
6563 void device_resource_released(IWineD3DDeviceImpl *device, IWineD3DResource *resource)
6564 {
6565     WINED3DRESOURCETYPE type = IWineD3DResource_GetType(resource);
6566     unsigned int i;
6567
6568     TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type));
6569
6570     context_resource_released(device, resource, type);
6571
6572     switch (type)
6573     {
6574         case WINED3DRTYPE_SURFACE:
6575             if (!device->d3d_initialized) break;
6576
6577             for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
6578             {
6579                 if (device->render_targets[i] == (IWineD3DSurfaceImpl *)resource)
6580                 {
6581                     ERR("Surface %p is still in use as render target %u.\n", resource, i);
6582                     device->render_targets[i] = NULL;
6583                 }
6584             }
6585
6586             if (device->depth_stencil == (IWineD3DSurfaceImpl *)resource)
6587             {
6588                 ERR("Surface %p is still in use as depth/stencil buffer.\n", resource);
6589                 device->depth_stencil = NULL;
6590             }
6591             break;
6592
6593         case WINED3DRTYPE_TEXTURE:
6594         case WINED3DRTYPE_CUBETEXTURE:
6595         case WINED3DRTYPE_VOLUMETEXTURE:
6596             for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
6597             {
6598                 if (device->stateBlock && device->stateBlock->textures[i] == (IWineD3DBaseTexture *)resource)
6599                 {
6600                     ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6601                             resource, device->stateBlock, i);
6602                     device->stateBlock->textures[i] = NULL;
6603                 }
6604
6605                 if (device->updateStateBlock != device->stateBlock
6606                         && device->updateStateBlock->textures[i] == (IWineD3DBaseTexture *)resource)
6607                 {
6608                     ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6609                             resource, device->updateStateBlock, i);
6610                     device->updateStateBlock->textures[i] = NULL;
6611                 }
6612             }
6613             break;
6614
6615         case WINED3DRTYPE_BUFFER:
6616             for (i = 0; i < MAX_STREAMS; ++i)
6617             {
6618                 if (device->stateBlock && device->stateBlock->streams[i].buffer == (struct wined3d_buffer *)resource)
6619                 {
6620                     ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6621                             resource, device->stateBlock, i);
6622                     device->stateBlock->streams[i].buffer = NULL;
6623                 }
6624
6625                 if (device->updateStateBlock != device->stateBlock
6626                         && device->updateStateBlock->streams[i].buffer == (struct wined3d_buffer *)resource)
6627                 {
6628                     ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6629                             resource, device->updateStateBlock, i);
6630                     device->updateStateBlock->streams[i].buffer = NULL;
6631                 }
6632
6633             }
6634
6635             if (device->stateBlock && device->stateBlock->pIndexData == (IWineD3DBuffer *)resource)
6636             {
6637                 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6638                         resource, device->stateBlock);
6639                 device->stateBlock->pIndexData =  NULL;
6640             }
6641
6642             if (device->updateStateBlock != device->stateBlock
6643                     && device->updateStateBlock->pIndexData == (IWineD3DBuffer *)resource)
6644             {
6645                 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6646                         resource, device->updateStateBlock);
6647                 device->updateStateBlock->pIndexData =  NULL;
6648             }
6649             break;
6650
6651         default:
6652             break;
6653     }
6654
6655     /* Remove the resource from the resourceStore */
6656     device_resource_remove(device, resource);
6657
6658     TRACE("Resource released.\n");
6659 }
6660
6661 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
6662     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6663     IWineD3DResourceImpl *resource, *cursor;
6664     HRESULT ret;
6665     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
6666
6667     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6668         TRACE("enumerating resource %p\n", resource);
6669         IWineD3DResource_AddRef((IWineD3DResource *) resource);
6670         ret = pCallback((IWineD3DResource *) resource, pData);
6671         if(ret == S_FALSE) {
6672             TRACE("Canceling enumeration\n");
6673             break;
6674         }
6675     }
6676     return WINED3D_OK;
6677 }
6678
6679 static HRESULT WINAPI IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice *iface, HDC dc, IWineD3DSurface **surface)
6680 {
6681     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6682     IWineD3DResourceImpl *resource;
6683
6684     LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry)
6685     {
6686         WINED3DRESOURCETYPE type = IWineD3DResource_GetType((IWineD3DResource *)resource);
6687         if (type == WINED3DRTYPE_SURFACE)
6688         {
6689             if (((IWineD3DSurfaceImpl *)resource)->hDC == dc)
6690             {
6691                 TRACE("Found surface %p for dc %p.\n", resource, dc);
6692                 *surface = (IWineD3DSurface *)resource;
6693                 return WINED3D_OK;
6694             }
6695         }
6696     }
6697
6698     return WINED3DERR_INVALIDCALL;
6699 }
6700
6701 /**********************************************************
6702  * IWineD3DDevice VTbl follows
6703  **********************************************************/
6704
6705 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6706 {
6707     /*** IUnknown methods ***/
6708     IWineD3DDeviceImpl_QueryInterface,
6709     IWineD3DDeviceImpl_AddRef,
6710     IWineD3DDeviceImpl_Release,
6711     /*** IWineD3DDevice methods ***/
6712     /*** Creation methods**/
6713     IWineD3DDeviceImpl_CreateBuffer,
6714     IWineD3DDeviceImpl_CreateVertexBuffer,
6715     IWineD3DDeviceImpl_CreateIndexBuffer,
6716     IWineD3DDeviceImpl_CreateStateBlock,
6717     IWineD3DDeviceImpl_CreateSurface,
6718     IWineD3DDeviceImpl_CreateRendertargetView,
6719     IWineD3DDeviceImpl_CreateTexture,
6720     IWineD3DDeviceImpl_CreateVolumeTexture,
6721     IWineD3DDeviceImpl_CreateVolume,
6722     IWineD3DDeviceImpl_CreateCubeTexture,
6723     IWineD3DDeviceImpl_CreateQuery,
6724     IWineD3DDeviceImpl_CreateSwapChain,
6725     IWineD3DDeviceImpl_CreateVertexDeclaration,
6726     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
6727     IWineD3DDeviceImpl_CreateVertexShader,
6728     IWineD3DDeviceImpl_CreateGeometryShader,
6729     IWineD3DDeviceImpl_CreatePixelShader,
6730     IWineD3DDeviceImpl_CreatePalette,
6731     /*** Odd functions **/
6732     IWineD3DDeviceImpl_Init3D,
6733     IWineD3DDeviceImpl_InitGDI,
6734     IWineD3DDeviceImpl_Uninit3D,
6735     IWineD3DDeviceImpl_UninitGDI,
6736     IWineD3DDeviceImpl_SetMultithreaded,
6737     IWineD3DDeviceImpl_EvictManagedResources,
6738     IWineD3DDeviceImpl_GetAvailableTextureMem,
6739     IWineD3DDeviceImpl_GetBackBuffer,
6740     IWineD3DDeviceImpl_GetCreationParameters,
6741     IWineD3DDeviceImpl_GetDeviceCaps,
6742     IWineD3DDeviceImpl_GetDirect3D,
6743     IWineD3DDeviceImpl_GetDisplayMode,
6744     IWineD3DDeviceImpl_SetDisplayMode,
6745     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6746     IWineD3DDeviceImpl_GetRasterStatus,
6747     IWineD3DDeviceImpl_GetSwapChain,
6748     IWineD3DDeviceImpl_Reset,
6749     IWineD3DDeviceImpl_SetDialogBoxMode,
6750     IWineD3DDeviceImpl_SetCursorProperties,
6751     IWineD3DDeviceImpl_SetCursorPosition,
6752     IWineD3DDeviceImpl_ShowCursor,
6753     /*** Getters and setters **/
6754     IWineD3DDeviceImpl_SetClipPlane,
6755     IWineD3DDeviceImpl_GetClipPlane,
6756     IWineD3DDeviceImpl_SetClipStatus,
6757     IWineD3DDeviceImpl_GetClipStatus,
6758     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6759     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6760     IWineD3DDeviceImpl_SetDepthStencilSurface,
6761     IWineD3DDeviceImpl_GetDepthStencilSurface,
6762     IWineD3DDeviceImpl_SetGammaRamp,
6763     IWineD3DDeviceImpl_GetGammaRamp,
6764     IWineD3DDeviceImpl_SetIndexBuffer,
6765     IWineD3DDeviceImpl_GetIndexBuffer,
6766     IWineD3DDeviceImpl_SetBaseVertexIndex,
6767     IWineD3DDeviceImpl_GetBaseVertexIndex,
6768     IWineD3DDeviceImpl_SetLight,
6769     IWineD3DDeviceImpl_GetLight,
6770     IWineD3DDeviceImpl_SetLightEnable,
6771     IWineD3DDeviceImpl_GetLightEnable,
6772     IWineD3DDeviceImpl_SetMaterial,
6773     IWineD3DDeviceImpl_GetMaterial,
6774     IWineD3DDeviceImpl_SetNPatchMode,
6775     IWineD3DDeviceImpl_GetNPatchMode,
6776     IWineD3DDeviceImpl_SetPaletteEntries,
6777     IWineD3DDeviceImpl_GetPaletteEntries,
6778     IWineD3DDeviceImpl_SetPixelShader,
6779     IWineD3DDeviceImpl_GetPixelShader,
6780     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6781     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6782     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6783     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6784     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6785     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6786     IWineD3DDeviceImpl_SetRenderState,
6787     IWineD3DDeviceImpl_GetRenderState,
6788     IWineD3DDeviceImpl_SetRenderTarget,
6789     IWineD3DDeviceImpl_GetRenderTarget,
6790     IWineD3DDeviceImpl_SetFrontBackBuffers,
6791     IWineD3DDeviceImpl_SetSamplerState,
6792     IWineD3DDeviceImpl_GetSamplerState,
6793     IWineD3DDeviceImpl_SetScissorRect,
6794     IWineD3DDeviceImpl_GetScissorRect,
6795     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6796     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6797     IWineD3DDeviceImpl_SetStreamSource,
6798     IWineD3DDeviceImpl_GetStreamSource,
6799     IWineD3DDeviceImpl_SetStreamSourceFreq,
6800     IWineD3DDeviceImpl_GetStreamSourceFreq,
6801     IWineD3DDeviceImpl_SetTexture,
6802     IWineD3DDeviceImpl_GetTexture,
6803     IWineD3DDeviceImpl_SetTextureStageState,
6804     IWineD3DDeviceImpl_GetTextureStageState,
6805     IWineD3DDeviceImpl_SetTransform,
6806     IWineD3DDeviceImpl_GetTransform,
6807     IWineD3DDeviceImpl_SetVertexDeclaration,
6808     IWineD3DDeviceImpl_GetVertexDeclaration,
6809     IWineD3DDeviceImpl_SetVertexShader,
6810     IWineD3DDeviceImpl_GetVertexShader,
6811     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6812     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6813     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6814     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6815     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6816     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6817     IWineD3DDeviceImpl_SetViewport,
6818     IWineD3DDeviceImpl_GetViewport,
6819     IWineD3DDeviceImpl_MultiplyTransform,
6820     IWineD3DDeviceImpl_ValidateDevice,
6821     IWineD3DDeviceImpl_ProcessVertices,
6822     /*** State block ***/
6823     IWineD3DDeviceImpl_BeginStateBlock,
6824     IWineD3DDeviceImpl_EndStateBlock,
6825     /*** Scene management ***/
6826     IWineD3DDeviceImpl_BeginScene,
6827     IWineD3DDeviceImpl_EndScene,
6828     IWineD3DDeviceImpl_Present,
6829     IWineD3DDeviceImpl_Clear,
6830     IWineD3DDeviceImpl_ClearRendertargetView,
6831     /*** Drawing ***/
6832     IWineD3DDeviceImpl_SetPrimitiveType,
6833     IWineD3DDeviceImpl_GetPrimitiveType,
6834     IWineD3DDeviceImpl_DrawPrimitive,
6835     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6836     IWineD3DDeviceImpl_DrawPrimitiveUP,
6837     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6838     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6839     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
6840     IWineD3DDeviceImpl_DrawRectPatch,
6841     IWineD3DDeviceImpl_DrawTriPatch,
6842     IWineD3DDeviceImpl_DeletePatch,
6843     IWineD3DDeviceImpl_ColorFill,
6844     IWineD3DDeviceImpl_UpdateTexture,
6845     IWineD3DDeviceImpl_UpdateSurface,
6846     IWineD3DDeviceImpl_GetFrontBufferData,
6847     /*** object tracking ***/
6848     IWineD3DDeviceImpl_EnumResources,
6849     IWineD3DDeviceImpl_GetSurfaceFromDC,
6850     IWineD3DDeviceImpl_AcquireFocusWindow,
6851     IWineD3DDeviceImpl_ReleaseFocusWindow,
6852 };
6853
6854 HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d,
6855         UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags,
6856         IWineD3DDeviceParent *device_parent)
6857 {
6858     struct wined3d_adapter *adapter = &wined3d->adapters[adapter_idx];
6859     const struct fragment_pipeline *fragment_pipeline;
6860     struct shader_caps shader_caps;
6861     struct fragment_caps ffp_caps;
6862     WINED3DDISPLAYMODE mode;
6863     unsigned int i;
6864     HRESULT hr;
6865
6866     device->lpVtbl = &IWineD3DDevice_Vtbl;
6867     device->ref = 1;
6868     device->wined3d = (IWineD3D *)wined3d;
6869     IWineD3D_AddRef(device->wined3d);
6870     device->adapter = wined3d->adapter_count ? adapter : NULL;
6871     device->device_parent = device_parent;
6872     list_init(&device->resources);
6873     list_init(&device->shaders);
6874
6875     device->surface_alignment = wined3d->dxVersion == 7 ? DDRAW_PITCH_ALIGNMENT : D3D8_PITCH_ALIGNMENT;
6876     device->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
6877
6878     /* Get the initial screen setup for ddraw. */
6879     hr = IWineD3D_GetAdapterDisplayMode((IWineD3D *)wined3d, adapter_idx, &mode);
6880     if (FAILED(hr))
6881     {
6882         ERR("Failed to get the adapter's display mode, hr %#x.\n", hr);
6883         IWineD3D_Release(device->wined3d);
6884         return hr;
6885     }
6886     device->ddraw_width = mode.Width;
6887     device->ddraw_height = mode.Height;
6888     device->ddraw_format = mode.Format;
6889
6890     /* Save the creation parameters. */
6891     device->createParms.AdapterOrdinal = adapter_idx;
6892     device->createParms.DeviceType = device_type;
6893     device->createParms.hFocusWindow = focus_window;
6894     device->createParms.BehaviorFlags = flags;
6895
6896     device->devType = device_type;
6897     for (i = 0; i < PATCHMAP_SIZE; ++i) list_init(&device->patches[i]);
6898
6899     select_shader_mode(&adapter->gl_info, &device->ps_selected_mode, &device->vs_selected_mode);
6900     device->shader_backend = adapter->shader_backend;
6901
6902     if (device->shader_backend)
6903     {
6904         device->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
6905         device->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
6906         device->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
6907         device->vs_clipping = shader_caps.VSClipping;
6908     }
6909     fragment_pipeline = adapter->fragment_pipe;
6910     device->frag_pipe = fragment_pipeline;
6911     if (fragment_pipeline)
6912     {
6913         fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
6914         device->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
6915
6916         hr = compile_state_table(device->StateTable, device->multistate_funcs, &adapter->gl_info,
6917                                  ffp_vertexstate_template, fragment_pipeline, misc_state_template);
6918         if (FAILED(hr))
6919         {
6920             ERR("Failed to compile state table, hr %#x.\n", hr);
6921             IWineD3D_Release(device->wined3d);
6922             return hr;
6923         }
6924     }
6925     device->blitter = adapter->blitter;
6926
6927     return WINED3D_OK;
6928 }
6929
6930
6931 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6932     DWORD rep = This->StateTable[state].representative;
6933     struct wined3d_context *context;
6934     DWORD idx;
6935     BYTE shift;
6936     UINT i;
6937
6938     for(i = 0; i < This->numContexts; i++) {
6939         context = This->contexts[i];
6940         if(isStateDirty(context, rep)) continue;
6941
6942         context->dirtyArray[context->numDirtyEntries++] = rep;
6943         idx = rep / (sizeof(*context->isStateDirty) * CHAR_BIT);
6944         shift = rep & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1);
6945         context->isStateDirty[idx] |= (1 << shift);
6946     }
6947 }
6948
6949 void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height)
6950 {
6951     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
6952     *width = context->current_rt->pow2Width;
6953     *height = context->current_rt->pow2Height;
6954 }
6955
6956 void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height)
6957 {
6958     IWineD3DSwapChainImpl *swapchain = context->swapchain;
6959     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
6960      * current context's drawable, which is the size of the back buffer of the swapchain
6961      * the active context belongs to. */
6962     *width = swapchain->presentParms.BackBufferWidth;
6963     *height = swapchain->presentParms.BackBufferHeight;
6964 }
6965
6966 LRESULT device_process_message(IWineD3DDeviceImpl *device, HWND window,
6967         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
6968 {
6969     if (device->filter_messages)
6970     {
6971         TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
6972                 window, message, wparam, lparam);
6973         return DefWindowProcW(window, message, wparam, lparam);
6974     }
6975
6976     if (message == WM_DESTROY)
6977     {
6978         TRACE("unregister window %p.\n", window);
6979         wined3d_unregister_window(window);
6980
6981         if (device->focus_window == window) device->focus_window = NULL;
6982         else ERR("Window %p is not the focus window for device %p.\n", window, device);
6983     }
6984
6985     return CallWindowProcW(proc, window, message, wparam, lparam);
6986 }