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