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