VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c@ 39016

Last change on this file since 39016 was 38982, checked in by vboxsync, 13 years ago

wddm: proper ie rendering under win8 (shared resource open & destroy fixes, zero-init resources on creaate, etc.)

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette