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