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