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