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