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