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