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