ReactOS 0.4.16-dev-122-g325d74c
device.c
Go to the documentation of this file.
1/*
2 * Copyright 2002 Lionel Ulmer
3 * Copyright 2002-2005 Jason Edmeades
4 * Copyright 2003-2004 Raphael Junqueira
5 * Copyright 2004 Christian Costa
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
8 * Copyright 2006-2008 Henri Verbeet
9 * Copyright 2007 Andrew Riedi
10 * Copyright 2009-2011 Henri Verbeet for CodeWeavers
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include "config.h"
28#include "wine/port.h"
29
30#include <stdio.h>
31#ifdef HAVE_FLOAT_H
32# include <float.h>
33#endif
34
35#include "wined3d_private.h"
36
39
40/* Define the default light parameters as specified by MSDN. */
42{
44 { 1.0f, 1.0f, 1.0f, 0.0f }, /* Diffuse r,g,b,a */
45 { 0.0f, 0.0f, 0.0f, 0.0f }, /* Specular r,g,b,a */
46 { 0.0f, 0.0f, 0.0f, 0.0f }, /* Ambient r,g,b,a, */
47 { 0.0f, 0.0f, 0.0f }, /* Position x,y,z */
48 { 0.0f, 0.0f, 1.0f }, /* Direction x,y,z */
49 0.0f, /* Range */
50 0.0f, /* Falloff */
51 0.0f, 0.0f, 0.0f, /* Attenuation 0,1,2 */
52 0.0f, /* Theta */
53 0.0f /* Phi */
54};
55
56/* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
57 * actually have the same values in GL and D3D. */
59{
60 switch (primitive_type)
61 {
63 return GL_POINTS;
64
66 return GL_LINES;
67
69 return GL_LINE_STRIP;
70
72 return GL_TRIANGLES;
73
75 return GL_TRIANGLE_STRIP;
76
78 return GL_TRIANGLE_FAN;
79
82
85
88
91
93 return GL_PATCHES;
94
95 default:
96 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type));
98 return ~0u;
99 }
100}
101
103{
104 switch (primitive_type)
105 {
106 case GL_POINTS:
108
109 case GL_LINES:
110 return WINED3D_PT_LINELIST;
111
112 case GL_LINE_STRIP:
114
115 case GL_TRIANGLES:
117
120
121 case GL_TRIANGLE_FAN:
123
126
129
132
135
136 case GL_PATCHES:
137 return WINED3D_PT_PATCH;
138
139 default:
140 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type));
141 case ~0u:
143 }
144}
145
147{
148 struct wined3d_context **new_array;
149
150 TRACE("Adding context %p.\n", context);
151
152 if (!(new_array = heap_realloc(device->contexts, sizeof(*new_array) * (device->context_count + 1))))
153 {
154 ERR("Failed to grow the context array.\n");
155 return FALSE;
156 }
157
158 new_array[device->context_count++] = context;
159 device->contexts = new_array;
160 return TRUE;
161}
162
164{
165 struct wined3d_context **new_array;
166 BOOL found = FALSE;
167 UINT i;
168
169 TRACE("Removing context %p.\n", context);
170
171 for (i = 0; i < device->context_count; ++i)
172 {
173 if (device->contexts[i] == context)
174 {
175 found = TRUE;
176 break;
177 }
178 }
179
180 if (!found)
181 {
182 ERR("Context %p doesn't exist in context array.\n", context);
183 return;
184 }
185
186 if (!--device->context_count)
187 {
188 heap_free(device->contexts);
189 device->contexts = NULL;
190 return;
191 }
192
193 memmove(&device->contexts[i], &device->contexts[i + 1], (device->context_count - i) * sizeof(*device->contexts));
194 if (!(new_array = heap_realloc(device->contexts, device->context_count * sizeof(*device->contexts))))
195 {
196 ERR("Failed to shrink context array. Oh well.\n");
197 return;
198 }
199
200 device->contexts = new_array;
201}
202
203static BOOL is_full_clear(const struct wined3d_texture *texture, unsigned int sub_resource_idx,
204 const RECT *draw_rect, const RECT *clear_rect)
205{
206 unsigned int width, height, level;
207
208 level = sub_resource_idx % texture->level_count;
211
212 /* partial draw rect */
213 if (draw_rect->left || draw_rect->top || draw_rect->right < width || draw_rect->bottom < height)
214 return FALSE;
215
216 /* partial clear rect */
217 if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0
218 || clear_rect->right < width || clear_rect->bottom < height))
219 return FALSE;
220
221 return TRUE;
222}
223
225 UINT rect_count, const RECT *clear_rect, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color,
226 float depth, DWORD stencil)
227{
228 struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL;
231 struct wined3d_surface *depth_stencil = dsv ? wined3d_rendertarget_view_get_surface(dsv) : NULL;
232 const struct wined3d_state *state = &device->cs->state;
233 const struct wined3d_gl_info *gl_info;
234 UINT drawable_width, drawable_height;
235 struct wined3d_color corrected_color;
236 struct wined3d_context *context;
237 GLbitfield clear_mask = 0;
239 unsigned int i;
240
241 if (target)
243 else
245 if (!context->valid)
246 {
248 WARN("Invalid context, skipping clear.\n");
249 return;
250 }
251 gl_info = context->gl_info;
252
253 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
254 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
255 * for the cleared parts, and the untouched parts.
256 *
257 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
258 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
259 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
260 * checking all this if the dest surface is in the drawable anyway. */
261 for (i = 0; i < rt_count; ++i)
262 {
263 struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
264
265 if (rtv && rtv->format->id != WINED3DFMT_NULL)
266 {
268
270 draw_rect, rect_count ? clear_rect : NULL))
271 wined3d_texture_load_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
272 else
274 }
275 }
276
277 if (target)
278 {
279 render_offscreen = context->render_offscreen;
280 wined3d_rendertarget_view_get_drawable_size(rtv, context, &drawable_width, &drawable_height);
281 }
282 else
283 {
284 unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->container->level_count;
285
286 render_offscreen = TRUE;
287 drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil->container, ds_level);
288 drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil->container, ds_level);
289 }
290
291 if (depth_stencil)
292 {
293 DWORD ds_location = render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
295
297 && !is_full_clear(ds, dsv->sub_resource_idx, draw_rect, rect_count ? clear_rect : NULL))
299 else
301
303 {
306 }
307 }
308
309 if (!context_apply_clear_state(context, state, rt_count, fb))
310 {
312 WARN("Failed to apply clear state, skipping clear.\n");
313 return;
314 }
315
316 /* Only set the values up once, as they are not changing. */
318 {
319 if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
320 {
321 gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
323 }
324 gl_info->gl_ops.gl.p_glStencilMask(~0U);
326 gl_info->gl_ops.gl.p_glClearStencil(stencil);
327 checkGLcall("glClearStencil");
328 clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
329 }
330
332 {
333 gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
335 gl_info->gl_ops.gl.p_glClearDepth(depth);
336 checkGLcall("glClearDepth");
337 clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
338 }
339
341 {
342 for (i = 0; i < rt_count; ++i)
343 {
344 struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
345 struct wined3d_texture *texture;
346
347 if (!rtv)
348 continue;
349
350 if (rtv->resource->type == WINED3D_RTYPE_BUFFER)
351 {
352 FIXME("Not supported on buffer resources.\n");
353 continue;
354 }
355
359 }
360
362 {
363 if (rt_count > 1)
364 WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB "
365 "support, this might cause graphical issues.\n");
366
367 corrected_color.r = color->r < wined3d_srgb_const1[0]
368 ? color->r * wined3d_srgb_const0[3]
371 corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f);
372 corrected_color.g = color->g < wined3d_srgb_const1[0]
373 ? color->g * wined3d_srgb_const0[3]
376 corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f);
377 corrected_color.b = color->b < wined3d_srgb_const1[0]
378 ? color->b * wined3d_srgb_const0[3]
381 corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f);
382 color = &corrected_color;
383 }
384
385 gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
386 for (i = 0; i < MAX_RENDER_TARGETS; ++i)
388 gl_info->gl_ops.gl.p_glClearColor(color->r, color->g, color->b, color->a);
389 checkGLcall("glClearColor");
390 clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
391 }
392
393 if (!rect_count)
394 {
395 if (render_offscreen)
396 {
397 gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top,
398 draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
399 }
400 else
401 {
402 gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
403 draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
404 }
405 checkGLcall("glScissor");
406 gl_info->gl_ops.gl.p_glClear(clear_mask);
407 checkGLcall("glClear");
408 }
409 else
410 {
411 RECT current_rect;
412
413 /* Now process each rect in turn. */
414 for (i = 0; i < rect_count; ++i)
415 {
416 /* Note that GL uses lower left, width/height. */
417 IntersectRect(&current_rect, draw_rect, &clear_rect[i]);
418
419 TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
420 wine_dbgstr_rect(&clear_rect[i]),
421 wine_dbgstr_rect(&current_rect));
422
423 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
424 * The rectangle is not cleared, no error is returned, but further rectangles are
425 * still cleared if they are valid. */
426 if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
427 {
428 TRACE("Rectangle with negative dimensions, ignoring.\n");
429 continue;
430 }
431
432 if (render_offscreen)
433 {
434 gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top,
435 current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
436 }
437 else
438 {
439 gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
440 current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
441 }
442 checkGLcall("glScissor");
443
444 gl_info->gl_ops.gl.p_glClear(clear_mask);
445 checkGLcall("glClear");
446 }
447 }
448
450 && target->container->swapchain && target->container->swapchain->front_buffer == target->container))
451 gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
452
454}
455
457{
458 ULONG refcount = InterlockedIncrement(&device->ref);
459
460 TRACE("%p increasing refcount to %u.\n", device, refcount);
461
462 return refcount;
463}
464
466{
468
469 ERR("Leftover sampler %p.\n", sampler);
470}
471
473{
475
476 TRACE("%p decreasing refcount to %u.\n", device, refcount);
477
478 if (!refcount)
479 {
480 UINT i;
481
483
484 if (device->recording && wined3d_stateblock_decref(device->recording))
485 ERR("Something's still holding the recording stateblock.\n");
486 device->recording = NULL;
487
488 state_cleanup(&device->state);
489
490 for (i = 0; i < ARRAY_SIZE(device->multistate_funcs); ++i)
491 {
492 heap_free(device->multistate_funcs[i]);
493 device->multistate_funcs[i] = NULL;
494 }
495
496 if (!list_empty(&device->resources))
497 {
499
500 ERR("Device released with resources still bound.\n");
501
503 {
504 ERR("Leftover resource %p with type %s (%#x).\n",
506 }
507 }
508
509 if (device->contexts)
510 ERR("Context array not freed!\n");
511 if (device->hardwareCursor)
512 DestroyCursor(device->hardwareCursor);
513 device->hardwareCursor = 0;
514
516
517 wined3d_decref(device->wined3d);
518 device->wined3d = NULL;
520 TRACE("Freed device %p.\n", device);
521 }
522
523 return refcount;
524}
525
527{
528 TRACE("device %p.\n", device);
529
530 return device->swapchain_count;
531}
532
534{
535 TRACE("device %p, swapchain_idx %u.\n", device, swapchain_idx);
536
537 if (swapchain_idx >= device->swapchain_count)
538 {
539 WARN("swapchain_idx %u >= swapchain_count %u.\n",
540 swapchain_idx, device->swapchain_count);
541 return NULL;
542 }
543
544 return device->swapchains[swapchain_idx];
545}
546
547static void device_load_logo(struct wined3d_device *device, const char *filename)
548{
551 HBITMAP hbm;
552 BITMAP bm;
553 HRESULT hr;
554 HDC dcb = NULL, dcs = NULL;
555
557 {
558 ERR_(winediag)("Failed to load logo %s.\n", wine_dbgstr_a(filename));
559 return;
560 }
561 GetObjectA(hbm, sizeof(BITMAP), &bm);
562
563 if (!(dcb = CreateCompatibleDC(NULL)))
564 goto out;
565 SelectObject(dcb, hbm);
566
567 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
569 desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
570 desc.multisample_quality = 0;
573 desc.width = bm.bmWidth;
574 desc.height = bm.bmHeight;
575 desc.depth = 1;
576 desc.size = 0;
579 NULL, NULL, &wined3d_null_parent_ops, &device->logo_texture)))
580 {
581 ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr);
582 goto out;
583 }
584
585 if (FAILED(hr = wined3d_texture_get_dc(device->logo_texture, 0, &dcs)))
586 {
587 wined3d_texture_decref(device->logo_texture);
588 device->logo_texture = NULL;
589 goto out;
590 }
591 BitBlt(dcs, 0, 0, bm.bmWidth, bm.bmHeight, dcb, 0, 0, SRCCOPY);
592 wined3d_texture_release_dc(device->logo_texture, 0, dcs);
593
594 color_key.color_space_low_value = 0;
595 color_key.color_space_high_value = 0;
597
598out:
599 if (dcb) DeleteDC(dcb);
600 if (hbm) DeleteObject(hbm);
601}
602
603/* Context activation is done by the caller. */
605{
606 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
607 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
608 struct wined3d_dummy_textures *textures = &device->dummy_textures;
609 unsigned int i;
610 DWORD color;
611
613 color = 0x000000ff;
614 else
615 color = 0x00000000;
616
617 /* Under DirectX you can sample even if no texture is bound, whereas
618 * OpenGL will only allow that when a valid texture is bound.
619 * We emulate this by creating dummy textures and binding them
620 * to each texture stage when the currently set D3D texture is NULL. */
621 context_active_texture(context, gl_info, 0);
622
623 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d);
624 TRACE("Dummy 1D texture given name %u.\n", textures->tex_1d);
625 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, textures->tex_1d);
626 gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 1, 0,
628
629 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d);
630 TRACE("Dummy 2D texture given name %u.\n", textures->tex_2d);
631 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, textures->tex_2d);
632 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0,
634
635 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
636 {
637 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_rect);
638 TRACE("Dummy rectangle texture given name %u.\n", textures->tex_rect);
639 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures->tex_rect);
640 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 1, 1, 0,
642 }
643
644 if (gl_info->supported[EXT_TEXTURE3D])
645 {
646 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_3d);
647 TRACE("Dummy 3D texture given name %u.\n", textures->tex_3d);
648 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, textures->tex_3d);
651 }
652
653 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
654 {
655 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube);
656 TRACE("Dummy cube texture given name %u.\n", textures->tex_cube);
657 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP, textures->tex_cube);
659 {
660 gl_info->gl_ops.gl.p_glTexImage2D(i, 0, GL_RGBA8, 1, 1, 0,
662 }
663 }
664
666 {
667 DWORD cube_array_data[6];
668
669 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_cube_array);
670 TRACE("Dummy cube array texture given name %u.\n", textures->tex_cube_array);
671 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures->tex_cube_array);
672 for (i = 0; i < ARRAY_SIZE(cube_array_data); ++i)
673 cube_array_data[i] = color;
675 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cube_array_data));
676 }
677
678 if (gl_info->supported[EXT_TEXTURE_ARRAY])
679 {
680
681 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_1d_array);
682 TRACE("Dummy 1D array texture given name %u.\n", textures->tex_1d_array);
683 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D_ARRAY, textures->tex_1d_array);
684 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, 1, 1, 0,
686
687 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_array);
688 TRACE("Dummy 2D array texture given name %u.\n", textures->tex_2d_array);
689 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_ARRAY, textures->tex_2d_array);
692 }
693
695 {
697
698 GL_EXTCALL(glGenBuffers(1, &buffer));
699 GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, buffer));
700 GL_EXTCALL(glBufferData(GL_TEXTURE_BUFFER, sizeof(color), &color, GL_STATIC_DRAW));
701 GL_EXTCALL(glBindBuffer(GL_TEXTURE_BUFFER, 0));
702
703 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_buffer);
704 TRACE("Dummy buffer texture given name %u.\n", textures->tex_buffer);
705 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_BUFFER, textures->tex_buffer);
707 GL_EXTCALL(glDeleteBuffers(1, &buffer));
708 }
709
711 {
712 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms);
713 TRACE("Dummy multisample texture given name %u.\n", textures->tex_2d_ms);
714 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures->tex_2d_ms);
715 GL_EXTCALL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, GL_TRUE));
716
717 gl_info->gl_ops.gl.p_glGenTextures(1, &textures->tex_2d_ms_array);
718 TRACE("Dummy multisample array texture given name %u.\n", textures->tex_2d_ms_array);
719 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures->tex_2d_ms_array);
720 GL_EXTCALL(glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 1, 1, 1, GL_TRUE));
721
722 if (gl_info->supported[ARB_CLEAR_TEXTURE])
723 {
724 GL_EXTCALL(glClearTexImage(textures->tex_2d_ms, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
725 GL_EXTCALL(glClearTexImage(textures->tex_2d_ms_array, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &color));
726 }
727 else
728 {
729 WARN("ARB_clear_texture is currently required to clear dummy multisample textures.\n");
730 }
731 }
732
733 checkGLcall("create dummy textures");
734
736}
737
738/* Context activation is done by the caller. */
740{
741 struct wined3d_dummy_textures *dummy_textures = &device->dummy_textures;
742 const struct wined3d_gl_info *gl_info = context->gl_info;
743
745 {
746 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms);
747 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_ms_array);
748 }
749
751 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_buffer);
752
753 if (gl_info->supported[EXT_TEXTURE_ARRAY])
754 {
755 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d_array);
756 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d_array);
757 }
758
760 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube_array);
761
762 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
763 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_cube);
764
765 if (gl_info->supported[EXT_TEXTURE3D])
766 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_3d);
767
768 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
769 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_rect);
770
771 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_2d);
772 gl_info->gl_ops.gl.p_glDeleteTextures(1, &dummy_textures->tex_1d);
773
774 checkGLcall("delete dummy textures");
775
776 memset(dummy_textures, 0, sizeof(*dummy_textures));
777}
778
779/* Context activation is done by the caller. */
781{
783 HRESULT hr;
784
785 desc.address_u = WINED3D_TADDRESS_WRAP;
786 desc.address_v = WINED3D_TADDRESS_WRAP;
787 desc.address_w = WINED3D_TADDRESS_WRAP;
788 memset(desc.border_color, 0, sizeof(desc.border_color));
789 desc.mag_filter = WINED3D_TEXF_POINT;
790 desc.min_filter = WINED3D_TEXF_POINT;
791 desc.mip_filter = WINED3D_TEXF_NONE;
792 desc.lod_bias = 0.0f;
793 desc.min_lod = -1000.0f;
794 desc.max_lod = 1000.0f;
795 desc.mip_base_level = 0;
796 desc.max_anisotropy = 1;
797 desc.compare = FALSE;
798 desc.comparison_func = WINED3D_CMP_NEVER;
799 desc.srgb_decode = TRUE;
800
801 /* In SM4+ shaders there is a separation between resources and samplers. Some shader
802 * instructions allow access to resources without using samplers.
803 * In GLSL, resources are always accessed through sampler or image variables. The default
804 * sampler object is used to emulate the direct resource access when there is no sampler state
805 * to use.
806 */
808 {
809 ERR("Failed to create default sampler, hr %#x.\n", hr);
810 device->default_sampler = NULL;
811 }
812
813 /* In D3D10+, a NULL sampler maps to the default sampler state. */
814 desc.address_u = WINED3D_TADDRESS_CLAMP;
815 desc.address_v = WINED3D_TADDRESS_CLAMP;
816 desc.address_w = WINED3D_TADDRESS_CLAMP;
817 desc.mag_filter = WINED3D_TEXF_LINEAR;
818 desc.min_filter = WINED3D_TEXF_LINEAR;
819 desc.mip_filter = WINED3D_TEXF_LINEAR;
821 {
822 ERR("Failed to create null sampler, hr %#x.\n", hr);
823 device->null_sampler = NULL;
824 }
825}
826
827/* Context activation is done by the caller. */
829{
830 wined3d_sampler_decref(device->default_sampler);
831 device->default_sampler = NULL;
832 wined3d_sampler_decref(device->null_sampler);
833 device->null_sampler = NULL;
834}
835
837{
838 /* Make sure the window is managed, otherwise we won't get keyboard input. */
841
842 return style;
843}
844
846{
847 /* Filter out window decorations. */
848 exstyle &= ~(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
849
850 return exstyle;
851}
852
854{
855 BOOL filter_messages;
856 LONG style, exstyle;
857
858 TRACE("Setting up window %p for fullscreen mode.\n", window);
859
860 if (device->style || device->exStyle)
861 {
862 ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n",
863 window, device->style, device->exStyle);
864 }
865
868
869 style = fullscreen_style(device->style);
870 exstyle = fullscreen_exstyle(device->exStyle);
871
872 TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n",
873 device->style, device->exStyle, style, exstyle);
874
875 filter_messages = device->filter_messages;
876 device->filter_messages = TRUE;
877
881
882 device->filter_messages = filter_messages;
883}
884
886 const RECT *window_rect)
887{
888 unsigned int window_pos_flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
889 BOOL filter_messages;
890 LONG style, exstyle;
891 RECT rect = {0};
892
893 if (!device->style && !device->exStyle)
894 return;
895
898
899 /* These flags are set by wined3d_device_setup_fullscreen_window, not the
900 * application, and we want to ignore them in the test below, since it's
901 * not the application's fault that they changed. Additionally, we want to
902 * preserve the current status of these flags (i.e. don't restore them) to
903 * more closely emulate the behavior of Direct3D, which leaves these flags
904 * alone when returning to windowed mode. */
905 device->style ^= (device->style ^ style) & WS_VISIBLE;
906 device->exStyle ^= (device->exStyle ^ exstyle) & WS_EX_TOPMOST;
907
908 TRACE("Restoring window style of window %p to %08x, %08x.\n",
909 window, device->style, device->exStyle);
910
911 filter_messages = device->filter_messages;
912 device->filter_messages = TRUE;
913
914 /* Only restore the style if the application didn't modify it during the
915 * fullscreen phase. Some applications change it before calling Reset()
916 * when switching between windowed and fullscreen modes (HL2), some
917 * depend on the original style (Eve Online). */
918 if (style == fullscreen_style(device->style) && exstyle == fullscreen_exstyle(device->exStyle))
919 {
922 }
923
924 if (window_rect)
925 rect = *window_rect;
926 else
927 window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE);
928 SetWindowPos(window, 0, rect.left, rect.top,
929 rect.right - rect.left, rect.bottom - rect.top, window_pos_flags);
930
931 device->filter_messages = filter_messages;
932
933 /* Delete the old values. */
934 device->style = 0;
935 device->exStyle = 0;
936}
937
939{
940 TRACE("device %p, window %p.\n", device, window);
941
943 {
944 ERR("Failed to register window %p.\n", window);
945 return E_FAIL;
946 }
947
948 InterlockedExchangePointer((void **)&device->focus_window, window);
949 SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
950
951 return WINED3D_OK;
952}
953
955{
956 TRACE("device %p.\n", device);
957
958 if (device->focus_window) wined3d_unregister_window(device->focus_window);
959 InterlockedExchangePointer((void **)&device->focus_window, NULL);
960}
961
963{
964 BOOL ds_enable = swapchain->desc.enable_auto_depth_stencil;
965 unsigned int i;
966
967 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
968 {
970 }
971 if (device->back_buffer_view)
973
974 wined3d_device_set_depth_stencil_view(device, ds_enable ? device->auto_depth_stencil_view : NULL);
975}
976
978{
980 struct wined3d_device *device = object;
981 struct wined3d_context *context;
982 struct wined3d_shader *shader;
983
984 LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry)
985 {
986 TRACE("Unloading resource %p.\n", resource);
988 }
989
991 {
992 device->shader_backend->shader_destroy(shader);
993 }
994
996 device->blitter->ops->blitter_destroy(device->blitter, context);
997 device->shader_backend->shader_free_private(device);
1001
1002 while (device->context_count)
1003 {
1004 if (device->contexts[0]->swapchain)
1005 swapchain_destroy_contexts(device->contexts[0]->swapchain);
1006 else
1007 context_destroy(device, device->contexts[0]);
1008 }
1009}
1010
1012{
1014 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1015}
1016
1018{
1019 struct wined3d_device *device = object;
1020 struct wined3d_swapchain *swapchain;
1021 struct wined3d_context *context;
1022 struct wined3d_texture *target;
1023 HRESULT hr;
1024
1025 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
1026 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
1027 {
1028 ERR("Failed to allocate shader private data, hr %#x.\n", hr);
1029 return;
1030 }
1031
1032 if (!(device->blitter = wined3d_cpu_blitter_create()))
1033 {
1034 ERR("Failed to create CPU blitter.\n");
1035 device->shader_backend->shader_free_private(device);
1036 return;
1037 }
1038 wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info);
1040 wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info);
1041 wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info);
1042
1043 swapchain = device->swapchains[0];
1044 target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
1049}
1050
1052{
1054 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1055 if (!device->swapchains[0]->num_contexts)
1056 return E_FAIL;
1057
1058 return WINED3D_OK;
1059}
1060
1062 struct wined3d_swapchain_desc *swapchain_desc)
1063{
1064 static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f};
1065 struct wined3d_swapchain *swapchain = NULL;
1066 DWORD clear_flags = 0;
1067 HRESULT hr;
1068
1069 TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
1070
1071 if (device->d3d_initialized)
1073 if (device->wined3d->flags & WINED3D_NO3D)
1075
1076 memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets));
1077
1078 /* Setup the implicit swapchain. This also initializes a context. */
1079 TRACE("Creating implicit swapchain.\n");
1080 if (FAILED(hr = device->device_parent->ops->create_swapchain(device->device_parent,
1081 swapchain_desc, &swapchain)))
1082 {
1083 WARN("Failed to create implicit swapchain.\n");
1084 goto err_out;
1085 }
1086
1087 if (swapchain_desc->backbuffer_count)
1088 {
1089 struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
1090 struct wined3d_view_desc view_desc;
1091
1092 view_desc.format_id = back_buffer->format->id;
1093 view_desc.flags = 0;
1094 view_desc.u.texture.level_idx = 0;
1095 view_desc.u.texture.level_count = 1;
1096 view_desc.u.texture.layer_idx = 0;
1097 view_desc.u.texture.layer_count = 1;
1098 if (FAILED(hr = wined3d_rendertarget_view_create(&view_desc, back_buffer,
1099 NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
1100 {
1101 ERR("Failed to create rendertarget view, hr %#x.\n", hr);
1102 goto err_out;
1103 }
1104 }
1105
1106 device->swapchain_count = 1;
1107 if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
1108 {
1109 ERR("Out of memory!\n");
1110 goto err_out;
1111 }
1112 device->swapchains[0] = swapchain;
1113
1115 goto err_out;
1117
1118 device->contexts[0]->last_was_rhw = 0;
1119
1120 TRACE("All defaults now set up.\n");
1121
1122 /* Clear the screen */
1123 if (swapchain->back_buffers && swapchain->back_buffers[0])
1124 clear_flags |= WINED3DCLEAR_TARGET;
1125 if (swapchain_desc->enable_auto_depth_stencil)
1127 if (clear_flags)
1128 wined3d_device_clear(device, 0, NULL, clear_flags, &black, 1.0f, 0);
1129
1130 device->d3d_initialized = TRUE;
1131
1134 return WINED3D_OK;
1135
1136err_out:
1137 heap_free(device->swapchains);
1138 device->swapchain_count = 0;
1139 if (device->back_buffer_view)
1140 wined3d_rendertarget_view_decref(device->back_buffer_view);
1141 if (swapchain)
1142 wined3d_swapchain_decref(swapchain);
1143
1144 return hr;
1145}
1146
1148 struct wined3d_swapchain_desc *swapchain_desc)
1149{
1150 struct wined3d_swapchain *swapchain = NULL;
1151 HRESULT hr;
1152
1153 TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
1154
1155 /* Setup the implicit swapchain */
1156 TRACE("Creating implicit swapchain\n");
1157 hr = device->device_parent->ops->create_swapchain(device->device_parent,
1158 swapchain_desc, &swapchain);
1159 if (FAILED(hr))
1160 {
1161 WARN("Failed to create implicit swapchain\n");
1162 goto err_out;
1163 }
1164
1165 device->swapchain_count = 1;
1166 if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
1167 {
1168 ERR("Out of memory!\n");
1169 goto err_out;
1170 }
1171 device->swapchains[0] = swapchain;
1172
1173 if (!(device->blitter = wined3d_cpu_blitter_create()))
1174 {
1175 ERR("Failed to create CPU blitter.\n");
1176 heap_free(device->swapchains);
1177 device->swapchain_count = 0;
1178 goto err_out;
1179 }
1180
1181 return WINED3D_OK;
1182
1183err_out:
1184 wined3d_swapchain_decref(swapchain);
1185 return hr;
1186}
1187
1189{
1191
1193}
1194
1196{
1197 unsigned int i;
1198
1199 TRACE("device %p.\n", device);
1200
1201 if (!device->d3d_initialized)
1203
1204 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1205
1206 if (device->logo_texture)
1207 wined3d_texture_decref(device->logo_texture);
1208 if (device->cursor_texture)
1209 wined3d_texture_decref(device->cursor_texture);
1210
1212
1214
1215#if defined(STAGING_CSMT)
1217#endif /* STAGING_CSMT */
1219
1220 if (device->fb.depth_stencil)
1221 {
1222 struct wined3d_rendertarget_view *view = device->fb.depth_stencil;
1223
1224 TRACE("Releasing depth/stencil view %p.\n", view);
1225
1226 device->fb.depth_stencil = NULL;
1228 }
1229
1230 if (device->auto_depth_stencil_view)
1231 {
1232 struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view;
1233
1234 device->auto_depth_stencil_view = NULL;
1236 ERR("Something's still holding the auto depth/stencil view (%p).\n", view);
1237 }
1238
1239 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
1240 {
1242 }
1243 if (device->back_buffer_view)
1244 {
1245 wined3d_rendertarget_view_decref(device->back_buffer_view);
1246 device->back_buffer_view = NULL;
1247 }
1248
1249 for (i = 0; i < device->swapchain_count; ++i)
1250 {
1251 TRACE("Releasing the implicit swapchain %u.\n", i);
1252 if (wined3d_swapchain_decref(device->swapchains[i]))
1253 FIXME("Something's still holding the implicit swapchain.\n");
1254 }
1255
1256 heap_free(device->swapchains);
1257 device->swapchains = NULL;
1258 device->swapchain_count = 0;
1259
1260 device->d3d_initialized = FALSE;
1261
1262 return WINED3D_OK;
1263}
1264
1266{
1267 unsigned int i;
1268
1269 device->blitter->ops->blitter_destroy(device->blitter, NULL);
1270
1271 for (i = 0; i < device->swapchain_count; ++i)
1272 {
1273 TRACE("Releasing the implicit swapchain %u.\n", i);
1274 if (wined3d_swapchain_decref(device->swapchains[i]))
1275 FIXME("Something's still holding the implicit swapchain.\n");
1276 }
1277
1278 heap_free(device->swapchains);
1279 device->swapchains = NULL;
1280 device->swapchain_count = 0;
1281 return WINED3D_OK;
1282}
1283
1284/* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
1285 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
1286 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
1287 *
1288 * There is no way to deactivate thread safety once it is enabled.
1289 */
1291{
1292 TRACE("device %p.\n", device);
1293
1294 /* For now just store the flag (needed in case of ddraw). */
1295 device->create_parms.flags |= WINED3DCREATE_MULTITHREADED;
1296}
1297
1299{
1300 /* const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; */
1301
1302 TRACE("device %p.\n", device);
1303
1304 /* We can not acquire the context unless there is a swapchain. */
1305 /*
1306 if (device->swapchains && gl_info->supported[NVX_GPU_MEMORY_INFO] &&
1307 !wined3d_settings.emulated_textureram)
1308 {
1309 GLint vram_free_kb;
1310 UINT64 vram_free;
1311
1312 struct wined3d_context *context = context_acquire(device, NULL, 0);
1313 gl_info->gl_ops.gl.p_glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &vram_free_kb);
1314 vram_free = (UINT64)vram_free_kb * 1024;
1315 context_release(context);
1316
1317 TRACE("Total 0x%s bytes. emulation 0x%s left, driver 0x%s left.\n",
1318 wine_dbgstr_longlong(device->adapter->vram_bytes),
1319 wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used),
1320 wine_dbgstr_longlong(vram_free));
1321
1322 vram_free = min(vram_free, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
1323 return min(UINT_MAX, vram_free);
1324 }
1325 */
1326
1327 TRACE("Emulating 0x%s bytes. 0x%s used, returning 0x%s left.\n",
1328 wine_dbgstr_longlong(device->adapter->vram_bytes),
1329 wine_dbgstr_longlong(device->adapter->vram_bytes_used),
1330 wine_dbgstr_longlong(device->adapter->vram_bytes - device->adapter->vram_bytes_used));
1331
1332 return min(UINT_MAX, device->adapter->vram_bytes - device->adapter->vram_bytes_used);
1333}
1334
1337{
1339 struct wined3d_buffer *prev_buffer;
1340
1341 TRACE("device %p, idx %u, buffer %p, offset %u.\n", device, idx, buffer, offset);
1342
1344 {
1345 WARN("Invalid stream output %u.\n", idx);
1346 return;
1347 }
1348
1349 stream = &device->update_state->stream_output[idx];
1350 prev_buffer = stream->buffer;
1351
1352 if (buffer)
1354 stream->buffer = buffer;
1355 stream->offset = offset;
1356 if (!device->recording)
1358 if (prev_buffer)
1359 wined3d_buffer_decref(prev_buffer);
1360}
1361
1363 UINT idx, UINT *offset)
1364{
1365 TRACE("device %p, idx %u, offset %p.\n", device, idx, offset);
1366
1368 {
1369 WARN("Invalid stream output %u.\n", idx);
1370 return NULL;
1371 }
1372
1373 if (offset)
1374 *offset = device->state.stream_output[idx].offset;
1375 return device->state.stream_output[idx].buffer;
1376}
1377
1380{
1382 struct wined3d_buffer *prev_buffer;
1383
1384 TRACE("device %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
1385 device, stream_idx, buffer, offset, stride);
1386
1387 if (stream_idx >= MAX_STREAMS)
1388 {
1389 WARN("Stream index %u out of range.\n", stream_idx);
1391 }
1392 else if (offset & 0x3)
1393 {
1394 WARN("Offset %u is not 4 byte aligned.\n", offset);
1396 }
1397
1398 stream = &device->update_state->streams[stream_idx];
1399 prev_buffer = stream->buffer;
1400
1401 if (device->recording)
1402 device->recording->changed.streamSource |= 1u << stream_idx;
1403
1404 if (prev_buffer == buffer
1405 && stream->stride == stride
1406 && stream->offset == offset)
1407 {
1408 TRACE("Application is setting the old values over, nothing to do.\n");
1409 return WINED3D_OK;
1410 }
1411
1412 stream->buffer = buffer;
1413 if (buffer)
1414 {
1415 stream->stride = stride;
1416 stream->offset = offset;
1418 }
1419
1420 if (!device->recording)
1422 if (prev_buffer)
1423 wined3d_buffer_decref(prev_buffer);
1424
1425 return WINED3D_OK;
1426}
1427
1429 UINT stream_idx, struct wined3d_buffer **buffer, UINT *offset, UINT *stride)
1430{
1431 const struct wined3d_stream_state *stream;
1432
1433 TRACE("device %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
1434 device, stream_idx, buffer, offset, stride);
1435
1436 if (stream_idx >= MAX_STREAMS)
1437 {
1438 WARN("Stream index %u out of range.\n", stream_idx);
1440 }
1441
1442 stream = &device->state.streams[stream_idx];
1443 *buffer = stream->buffer;
1444 if (offset)
1445 *offset = stream->offset;
1446 *stride = stream->stride;
1447
1448 return WINED3D_OK;
1449}
1450
1452{
1454 UINT old_flags, old_freq;
1455
1456 TRACE("device %p, stream_idx %u, divider %#x.\n", device, stream_idx, divider);
1457
1458 /* Verify input. At least in d3d9 this is invalid. */
1460 {
1461 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n");
1463 }
1464 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx)
1465 {
1466 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n");
1468 }
1469 if (!divider)
1470 {
1471 WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n");
1473 }
1474
1475 stream = &device->update_state->streams[stream_idx];
1476 old_flags = stream->flags;
1477 old_freq = stream->frequency;
1478
1480 stream->frequency = divider & 0x7fffff;
1481
1482 if (device->recording)
1483 device->recording->changed.streamFreq |= 1u << stream_idx;
1484 else if (stream->frequency != old_freq || stream->flags != old_flags)
1485 wined3d_cs_emit_set_stream_source_freq(device->cs, stream_idx, stream->frequency, stream->flags);
1486
1487 return WINED3D_OK;
1488}
1489
1491 UINT stream_idx, UINT *divider)
1492{
1493 const struct wined3d_stream_state *stream;
1494
1495 TRACE("device %p, stream_idx %u, divider %p.\n", device, stream_idx, divider);
1496
1497 stream = &device->state.streams[stream_idx];
1498 *divider = stream->flags | stream->frequency;
1499
1500 TRACE("Returning %#x.\n", *divider);
1501
1502 return WINED3D_OK;
1503}
1504
1506 enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1507{
1508 TRACE("device %p, state %s, matrix %p.\n",
1509 device, debug_d3dtstype(d3dts), matrix);
1510 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1511 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1512 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1513 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1514
1515 /* Handle recording of state blocks. */
1516 if (device->recording)
1517 {
1518 TRACE("Recording... not performing anything.\n");
1519 device->recording->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1520 device->update_state->transforms[d3dts] = *matrix;
1521 return;
1522 }
1523
1524 /* If the new matrix is the same as the current one,
1525 * we cut off any further processing. this seems to be a reasonable
1526 * optimization because as was noticed, some apps (warcraft3 for example)
1527 * tend towards setting the same matrix repeatedly for some reason.
1528 *
1529 * From here on we assume that the new matrix is different, wherever it matters. */
1530 if (!memcmp(&device->state.transforms[d3dts], matrix, sizeof(*matrix)))
1531 {
1532 TRACE("The application is setting the same matrix over again.\n");
1533 return;
1534 }
1535
1536 device->state.transforms[d3dts] = *matrix;
1538}
1539
1542{
1543 TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
1544
1545 *matrix = device->state.transforms[state];
1546}
1547
1550{
1551 const struct wined3d_matrix *mat;
1552 struct wined3d_matrix temp;
1553
1554 TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
1555
1556 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1557 * below means it will be recorded in a state block change, but it
1558 * works regardless where it is recorded.
1559 * If this is found to be wrong, change to StateBlock. */
1561 {
1562 WARN("Unhandled transform state %#x.\n", state);
1563 return;
1564 }
1565
1566 mat = &device->update_state->transforms[state];
1568
1569 /* Apply change via set transform - will reapply to eg. lights this way. */
1571}
1572
1573/* Note lights are real special cases. Although the device caps state only
1574 * e.g. 8 are supported, you can reference any indexes you want as long as
1575 * that number max are enabled at any one point in time. Therefore since the
1576 * indices can be anything, we need a hashmap of them. However, this causes
1577 * stateblock problems. When capturing the state block, I duplicate the
1578 * hashmap, but when recording, just build a chain pretty much of commands to
1579 * be replayed. */
1581 UINT light_idx, const struct wined3d_light *light)
1582{
1583 UINT hash_idx = LIGHTMAP_HASHFUNC(light_idx);
1584 struct wined3d_light_info *object = NULL;
1585 float rho;
1586
1587 TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
1588
1589 /* Check the parameter range. Need for speed most wanted sets junk lights
1590 * which confuse the GL driver. */
1591 if (!light)
1593
1594 switch (light->type)
1595 {
1597 case WINED3D_LIGHT_SPOT:
1599 /* Incorrect attenuation values can cause the gl driver to crash.
1600 * Happens with Need for speed most wanted. */
1601 if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f)
1602 {
1603 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n");
1605 }
1606 break;
1607
1610 /* Ignores attenuation */
1611 break;
1612
1613 default:
1614 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
1616 }
1617
1618 if (!(object = wined3d_state_get_light(device->update_state, light_idx)))
1619 {
1620 TRACE("Adding new light\n");
1621 if (!(object = heap_alloc_zero(sizeof(*object))))
1622 return E_OUTOFMEMORY;
1623
1624 list_add_head(&device->update_state->light_map[hash_idx], &object->entry);
1625 object->glIndex = -1;
1626 object->OriginalIndex = light_idx;
1627 }
1628
1629 /* Initialize the object. */
1630 TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, "
1631 "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, "
1632 "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n",
1633 light_idx, light->type, debug_color(&light->diffuse),
1634 debug_color(&light->specular), debug_color(&light->ambient),
1635 light->position.x, light->position.y, light->position.z,
1636 light->direction.x, light->direction.y, light->direction.z,
1637 light->range, light->falloff, light->theta, light->phi);
1638
1639 /* Save away the information. */
1640 object->OriginalParms = *light;
1641
1642 switch (light->type)
1643 {
1645 /* Position */
1646 object->position.x = light->position.x;
1647 object->position.y = light->position.y;
1648 object->position.z = light->position.z;
1649 object->position.w = 1.0f;
1650 object->cutoff = 180.0f;
1651 /* FIXME: Range */
1652 break;
1653
1655 /* Direction */
1656 object->direction.x = -light->direction.x;
1657 object->direction.y = -light->direction.y;
1658 object->direction.z = -light->direction.z;
1659 object->direction.w = 0.0f;
1660 object->exponent = 0.0f;
1661 object->cutoff = 180.0f;
1662 break;
1663
1664 case WINED3D_LIGHT_SPOT:
1665 /* Position */
1666 object->position.x = light->position.x;
1667 object->position.y = light->position.y;
1668 object->position.z = light->position.z;
1669 object->position.w = 1.0f;
1670
1671 /* Direction */
1672 object->direction.x = light->direction.x;
1673 object->direction.y = light->direction.y;
1674 object->direction.z = light->direction.z;
1675 object->direction.w = 0.0f;
1676
1677 /* opengl-ish and d3d-ish spot lights use too different models
1678 * for the light "intensity" as a function of the angle towards
1679 * the main light direction, so we only can approximate very
1680 * roughly. However, spot lights are rather rarely used in games
1681 * (if ever used at all). Furthermore if still used, probably
1682 * nobody pays attention to such details. */
1683 if (!light->falloff)
1684 {
1685 /* Falloff = 0 is easy, because d3d's and opengl's spot light
1686 * equations have the falloff resp. exponent parameter as an
1687 * exponent, so the spot light lighting will always be 1.0 for
1688 * both of them, and we don't have to care for the rest of the
1689 * rather complex calculation. */
1690 object->exponent = 0.0f;
1691 }
1692 else
1693 {
1694 rho = light->theta + (light->phi - light->theta) / (2 * light->falloff);
1695 if (rho < 0.0001f)
1696 rho = 0.0001f;
1697 object->exponent = -0.3f / logf(cosf(rho / 2));
1698 }
1699
1700 if (object->exponent > 128.0f)
1701 object->exponent = 128.0f;
1702
1703 object->cutoff = (float)(light->phi * 90 / M_PI);
1704 /* FIXME: Range */
1705 break;
1706
1708 object->position.x = light->position.x;
1709 object->position.y = light->position.y;
1710 object->position.z = light->position.z;
1711 object->position.w = 1.0f;
1712 break;
1713
1714 default:
1715 FIXME("Unrecognized light type %#x.\n", light->type);
1716 }
1717
1718 if (!device->recording)
1719 wined3d_cs_emit_set_light(device->cs, object);
1720
1721 return WINED3D_OK;
1722}
1723
1725 UINT light_idx, struct wined3d_light *light)
1726{
1727 struct wined3d_light_info *light_info;
1728
1729 TRACE("device %p, light_idx %u, light %p.\n", device, light_idx, light);
1730
1731 if (!(light_info = wined3d_state_get_light(&device->state, light_idx)))
1732 {
1733 TRACE("Light information requested but light not defined\n");
1735 }
1736
1737 *light = light_info->OriginalParms;
1738 return WINED3D_OK;
1739}
1740
1742{
1743 struct wined3d_light_info *light_info;
1744
1745 TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable);
1746
1747 /* Special case - enabling an undefined light creates one with a strict set of parameters. */
1748 if (!(light_info = wined3d_state_get_light(device->update_state, light_idx)))
1749 {
1750 TRACE("Light enabled requested but light not defined, so defining one!\n");
1752
1753 if (!(light_info = wined3d_state_get_light(device->update_state, light_idx)))
1754 {
1755 FIXME("Adding default lights has failed dismally\n");
1757 }
1758 }
1759
1760 wined3d_state_enable_light(device->update_state, &device->adapter->d3d_info, light_info, enable);
1761 if (!device->recording)
1763
1764 return WINED3D_OK;
1765}
1766
1768{
1769 struct wined3d_light_info *light_info;
1770
1771 TRACE("device %p, light_idx %u, enable %p.\n", device, light_idx, enable);
1772
1773 if (!(light_info = wined3d_state_get_light(&device->state, light_idx)))
1774 {
1775 TRACE("Light enabled state requested but light not defined.\n");
1777 }
1778 /* true is 128 according to SetLightEnable */
1779 *enable = light_info->enabled ? 128 : 0;
1780 return WINED3D_OK;
1781}
1782
1784 UINT plane_idx, const struct wined3d_vec4 *plane)
1785{
1786 TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
1787
1788 if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances)
1789 {
1790 TRACE("Application has requested clipplane this device doesn't support.\n");
1792 }
1793
1794 if (device->recording)
1795 device->recording->changed.clipplane |= 1u << plane_idx;
1796
1797 if (!memcmp(&device->update_state->clip_planes[plane_idx], plane, sizeof(*plane)))
1798 {
1799 TRACE("Application is setting old values over, nothing to do.\n");
1800 return WINED3D_OK;
1801 }
1802
1803 device->update_state->clip_planes[plane_idx] = *plane;
1804
1805 if (!device->recording)
1807
1808 return WINED3D_OK;
1809}
1810
1812 UINT plane_idx, struct wined3d_vec4 *plane)
1813{
1814 TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
1815
1816 if (plane_idx >= device->adapter->gl_info.limits.user_clip_distances)
1817 {
1818 TRACE("Application has requested clipplane this device doesn't support.\n");
1820 }
1821
1822 *plane = device->state.clip_planes[plane_idx];
1823
1824 return WINED3D_OK;
1825}
1826
1828 const struct wined3d_clip_status *clip_status)
1829{
1830 FIXME("device %p, clip_status %p stub!\n", device, clip_status);
1831
1832 if (!clip_status)
1834
1835 return WINED3D_OK;
1836}
1837
1839 struct wined3d_clip_status *clip_status)
1840{
1841 FIXME("device %p, clip_status %p stub!\n", device, clip_status);
1842
1843 if (!clip_status)
1845
1846 return WINED3D_OK;
1847}
1848
1850{
1851 TRACE("device %p, material %p.\n", device, material);
1852
1853 device->update_state->material = *material;
1854
1855 if (device->recording)
1856 device->recording->changed.material = TRUE;
1857 else
1858 wined3d_cs_emit_set_material(device->cs, material);
1859}
1860
1862{
1863 TRACE("device %p, material %p.\n", device, material);
1864
1865 *material = device->state.material;
1866
1867 TRACE("diffuse %s\n", debug_color(&material->diffuse));
1868 TRACE("ambient %s\n", debug_color(&material->ambient));
1869 TRACE("specular %s\n", debug_color(&material->specular));
1870 TRACE("emissive %s\n", debug_color(&material->emissive));
1871 TRACE("power %.8e.\n", material->power);
1872}
1873
1875 struct wined3d_buffer *buffer, enum wined3d_format_id format_id, unsigned int offset)
1876{
1877 enum wined3d_format_id prev_format;
1878 struct wined3d_buffer *prev_buffer;
1879 unsigned int prev_offset;
1880
1881 TRACE("device %p, buffer %p, format %s, offset %u.\n",
1883
1884 prev_buffer = device->update_state->index_buffer;
1885 prev_format = device->update_state->index_format;
1886 prev_offset = device->update_state->index_offset;
1887
1888 device->update_state->index_buffer = buffer;
1889 device->update_state->index_format = format_id;
1890 device->update_state->index_offset = offset;
1891
1892 if (device->recording)
1893 device->recording->changed.indices = TRUE;
1894
1895 if (prev_buffer == buffer && prev_format == format_id && prev_offset == offset)
1896 return;
1897
1898 if (buffer)
1900 if (!device->recording)
1902 if (prev_buffer)
1903 wined3d_buffer_decref(prev_buffer);
1904}
1905
1907 enum wined3d_format_id *format, unsigned int *offset)
1908{
1909 TRACE("device %p, format %p, offset %p.\n", device, format, offset);
1910
1911 *format = device->state.index_format;
1912 if (offset)
1913 *offset = device->state.index_offset;
1914 return device->state.index_buffer;
1915}
1916
1918{
1919 TRACE("device %p, base_index %d.\n", device, base_index);
1920
1921 device->update_state->base_vertex_index = base_index;
1922}
1923
1925{
1926 TRACE("device %p.\n", device);
1927
1928 return device->state.base_vertex_index;
1929}
1930
1932{
1933 TRACE("device %p, viewport %p.\n", device, viewport);
1934 TRACE("x %.8e, y %.8e, w %.8e, h %.8e, min_z %.8e, max_z %.8e.\n",
1935 viewport->x, viewport->y, viewport->width, viewport->height, viewport->min_z, viewport->max_z);
1936
1937 device->update_state->viewport = *viewport;
1938
1939 /* Handle recording of state blocks */
1940 if (device->recording)
1941 {
1942 TRACE("Recording... not performing anything\n");
1943 device->recording->changed.viewport = TRUE;
1944 return;
1945 }
1946
1947 wined3d_cs_emit_set_viewport(device->cs, viewport);
1948}
1949
1951{
1952 TRACE("device %p, viewport %p.\n", device, viewport);
1953
1954 *viewport = device->state.viewport;
1955}
1956
1958{
1959 const struct wined3d_state *state = &device->state;
1960 struct wined3d_rendertarget_view *src_view;
1961 struct wined3d_resource *dst_resource;
1962 struct wined3d_texture *dst_texture;
1963
1964 if (!(dst_texture = state->textures[0]))
1965 return;
1966 dst_resource = &dst_texture->resource;
1967 if (!(dst_resource->format_flags & WINED3DFMT_FLAG_DEPTH))
1968 return;
1969 if (!(src_view = state->fb->depth_stencil))
1970 return;
1971
1973 src_view->resource, src_view->sub_resource_idx, dst_resource->format->id);
1974}
1975
1977{
1978 struct wined3d_blend_state *prev;
1979
1980 TRACE("device %p, blend_state %p.\n", device, blend_state);
1981
1982 prev = device->update_state->blend_state;
1983 if (prev == blend_state)
1984 return;
1985
1986 if (blend_state)
1987 wined3d_blend_state_incref(blend_state);
1988 device->update_state->blend_state = blend_state;
1989 wined3d_cs_emit_set_blend_state(device->cs, blend_state);
1990 if (prev)
1992}
1993
1995{
1996 TRACE("device %p.\n", device);
1997
1998 return device->state.blend_state;
1999}
2000
2002 struct wined3d_rasterizer_state *rasterizer_state)
2003{
2004 struct wined3d_rasterizer_state *prev;
2005
2006 TRACE("device %p, rasterizer_state %p.\n", device, rasterizer_state);
2007
2008 prev = device->update_state->rasterizer_state;
2009 if (prev == rasterizer_state)
2010 return;
2011
2012 if (rasterizer_state)
2013 wined3d_rasterizer_state_incref(rasterizer_state);
2014 device->update_state->rasterizer_state = rasterizer_state;
2015 wined3d_cs_emit_set_rasterizer_state(device->cs, rasterizer_state);
2016 if (prev)
2018}
2019
2021{
2022 TRACE("device %p.\n", device);
2023
2024 return device->state.rasterizer_state;
2025}
2026
2029{
2031
2032 TRACE("device %p, state %s (%#x), value %#x.\n", device, debug_d3drenderstate(state), state, value);
2033
2035 {
2036 WARN("Unhandled render state %#x.\n", state);
2037 return;
2038 }
2039
2040 old_value = device->state.render_states[state];
2041 device->update_state->render_states[state] = value;
2042
2043 /* Handle recording of state blocks. */
2044 if (device->recording)
2045 {
2046 TRACE("Recording... not performing anything.\n");
2047 device->recording->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
2048 return;
2049 }
2050
2051 /* Compared here and not before the assignment to allow proper stateblock recording. */
2052 if (value == old_value)
2053 TRACE("Application is setting the old value over, nothing to do.\n");
2054 else
2056
2058 {
2059 TRACE("RESZ multisampled depth buffer resolve triggered.\n");
2061 }
2062}
2063
2065{
2066 TRACE("device %p, state %s (%#x).\n", device, debug_d3drenderstate(state), state);
2067
2068 return device->state.render_states[state];
2069}
2070
2072 UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
2073{
2075
2076 TRACE("device %p, sampler_idx %u, state %s, value %#x.\n",
2077 device, sampler_idx, debug_d3dsamplerstate(state), value);
2078
2079 if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
2081
2082 if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
2083 {
2084 WARN("Invalid sampler %u.\n", sampler_idx);
2085 return; /* Windows accepts overflowing this array ... we do not. */
2086 }
2087
2088 old_value = device->state.sampler_states[sampler_idx][state];
2089 device->update_state->sampler_states[sampler_idx][state] = value;
2090
2091 /* Handle recording of state blocks. */
2092 if (device->recording)
2093 {
2094 TRACE("Recording... not performing anything.\n");
2095 device->recording->changed.samplerState[sampler_idx] |= 1u << state;
2096 return;
2097 }
2098
2099 if (old_value == value)
2100 {
2101 TRACE("Application is setting the old value over, nothing to do.\n");
2102 return;
2103 }
2104
2106}
2107
2109 UINT sampler_idx, enum wined3d_sampler_state state)
2110{
2111 TRACE("device %p, sampler_idx %u, state %s.\n",
2112 device, sampler_idx, debug_d3dsamplerstate(state));
2113
2114 if (sampler_idx >= WINED3DVERTEXTEXTURESAMPLER0 && sampler_idx <= WINED3DVERTEXTEXTURESAMPLER3)
2116
2117 if (sampler_idx >= ARRAY_SIZE(device->state.sampler_states))
2118 {
2119 WARN("Invalid sampler %u.\n", sampler_idx);
2120 return 0; /* Windows accepts overflowing this array ... we do not. */
2121 }
2122
2123 return device->state.sampler_states[sampler_idx][state];
2124}
2125
2127{
2128 TRACE("device %p, rect %s.\n", device, wine_dbgstr_rect(rect));
2129
2130 if (device->recording)
2131 device->recording->changed.scissorRect = TRUE;
2132
2133 if (EqualRect(&device->update_state->scissor_rect, rect))
2134 {
2135 TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
2136 return;
2137 }
2138 CopyRect(&device->update_state->scissor_rect, rect);
2139
2140 if (device->recording)
2141 {
2142 TRACE("Recording... not performing anything.\n");
2143 return;
2144 }
2145
2147}
2148
2150{
2151 TRACE("device %p, rect %p.\n", device, rect);
2152
2153 *rect = device->state.scissor_rect;
2154 TRACE("Returning rect %s.\n", wine_dbgstr_rect(rect));
2155}
2156
2159{
2160 struct wined3d_vertex_declaration *prev = device->update_state->vertex_declaration;
2161
2162 TRACE("device %p, declaration %p.\n", device, declaration);
2163
2164 if (device->recording)
2165 device->recording->changed.vertexDecl = TRUE;
2166
2167 if (declaration == prev)
2168 return;
2169
2170 if (declaration)
2172 device->update_state->vertex_declaration = declaration;
2173 if (!device->recording)
2175 if (prev)
2177}
2178
2180{
2181 TRACE("device %p.\n", device);
2182
2183 return device->state.vertex_declaration;
2184}
2185
2187{
2188 struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX];
2189
2190 TRACE("device %p, shader %p.\n", device, shader);
2191
2192 if (device->recording)
2193 device->recording->changed.vertexShader = TRUE;
2194
2195 if (shader == prev)
2196 return;
2197
2198 if (shader)
2200 device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX] = shader;
2201 if (!device->recording)
2203 if (prev)
2205}
2206
2208{
2209 TRACE("device %p.\n", device);
2210
2211 return device->state.shader[WINED3D_SHADER_TYPE_VERTEX];
2212}
2213
2216{
2217 struct wined3d_buffer *prev;
2218
2220 {
2221 WARN("Invalid constant buffer index %u.\n", idx);
2222 return;
2223 }
2224
2225 prev = device->update_state->cb[type][idx];
2226 if (buffer == prev)
2227 return;
2228
2229 if (buffer)
2231 device->update_state->cb[type][idx] = buffer;
2232 if (!device->recording)
2234 if (prev)
2236}
2237
2239{
2240 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2241
2243}
2244
2246 enum wined3d_shader_type shader_type, unsigned int idx)
2247{
2249 {
2250 WARN("Invalid constant buffer index %u.\n", idx);
2251 return NULL;
2252 }
2253
2254 return device->state.cb[shader_type][idx];
2255}
2256
2258{
2259 TRACE("device %p, idx %u.\n", device, idx);
2260
2262}
2263
2266{
2267 struct wined3d_shader_resource_view *prev;
2268
2270 {
2271 WARN("Invalid view index %u.\n", idx);
2272 return;
2273 }
2274
2275 prev = device->update_state->shader_resource_view[type][idx];
2276 if (view == prev)
2277 return;
2278
2279 if (view)
2281 device->update_state->shader_resource_view[type][idx] = view;
2282 if (!device->recording)
2284 if (prev)
2286}
2287
2290{
2291 TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2292
2294}
2295
2297 const struct wined3d_device *device, enum wined3d_shader_type shader_type, unsigned int idx)
2298{
2300 {
2301 WARN("Invalid view index %u.\n", idx);
2302 return NULL;
2303 }
2304
2305 return device->state.shader_resource_view[shader_type][idx];
2306}
2307
2309 UINT idx)
2310{
2311 TRACE("device %p, idx %u.\n", device, idx);
2312
2314}
2315
2318{
2319 struct wined3d_sampler *prev;
2320
2321 if (idx >= MAX_SAMPLER_OBJECTS)
2322 {
2323 WARN("Invalid sampler index %u.\n", idx);
2324 return;
2325 }
2326
2327 prev = device->update_state->sampler[type][idx];
2328 if (sampler == prev)
2329 return;
2330
2331 if (sampler)
2333 device->update_state->sampler[type][idx] = sampler;
2334 if (!device->recording)
2336 if (prev)
2338}
2339
2341{
2342 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2343
2345}
2346
2348 enum wined3d_shader_type shader_type, unsigned int idx)
2349{
2350 if (idx >= MAX_SAMPLER_OBJECTS)
2351 {
2352 WARN("Invalid sampler index %u.\n", idx);
2353 return NULL;
2354 }
2355
2356 return device->state.sampler[shader_type][idx];
2357}
2358
2360{
2361 TRACE("device %p, idx %u.\n", device, idx);
2362
2364}
2365
2367 unsigned int start_idx, unsigned int count, const BOOL *constants)
2368{
2369 unsigned int i;
2370
2371 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2372 device, start_idx, count, constants);
2373
2374 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2376
2377 if (count > WINED3D_MAX_CONSTS_B - start_idx)
2378 count = WINED3D_MAX_CONSTS_B - start_idx;
2379 memcpy(&device->update_state->vs_consts_b[start_idx], constants, count * sizeof(*constants));
2380 if (TRACE_ON(d3d))
2381 {
2382 for (i = 0; i < count; ++i)
2383 TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2384 }
2385
2386 if (device->recording)
2387 {
2388 for (i = start_idx; i < count + start_idx; ++i)
2389 device->recording->changed.vertexShaderConstantsB |= (1u << i);
2390 }
2391 else
2392 {
2394 }
2395
2396 return WINED3D_OK;
2397}
2398
2400 unsigned int start_idx, unsigned int count, BOOL *constants)
2401{
2402 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2403 device, start_idx, count, constants);
2404
2405 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2407
2408 if (count > WINED3D_MAX_CONSTS_B - start_idx)
2409 count = WINED3D_MAX_CONSTS_B - start_idx;
2410 memcpy(constants, &device->state.vs_consts_b[start_idx], count * sizeof(*constants));
2411
2412 return WINED3D_OK;
2413}
2414
2416 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2417{
2418 unsigned int i;
2419
2420 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2421 device, start_idx, count, constants);
2422
2423 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2425
2426 if (count > WINED3D_MAX_CONSTS_I - start_idx)
2427 count = WINED3D_MAX_CONSTS_I - start_idx;
2428 memcpy(&device->update_state->vs_consts_i[start_idx], constants, count * sizeof(*constants));
2429 if (TRACE_ON(d3d))
2430 {
2431 for (i = 0; i < count; ++i)
2432 TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2433 }
2434
2435 if (device->recording)
2436 {
2437 for (i = start_idx; i < count + start_idx; ++i)
2438 device->recording->changed.vertexShaderConstantsI |= (1u << i);
2439 }
2440 else
2441 {
2443 }
2444
2445 return WINED3D_OK;
2446}
2447
2449 unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
2450{
2451 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2452 device, start_idx, count, constants);
2453
2454 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2456
2457 if (count > WINED3D_MAX_CONSTS_I - start_idx)
2458 count = WINED3D_MAX_CONSTS_I - start_idx;
2459 memcpy(constants, &device->state.vs_consts_i[start_idx], count * sizeof(*constants));
2460 return WINED3D_OK;
2461}
2462
2464 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2465{
2466 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2467 unsigned int i;
2468
2469 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2470 device, start_idx, count, constants);
2471
2472 if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
2473 || count > d3d_info->limits.vs_uniform_count - start_idx)
2475
2476 memcpy(&device->update_state->vs_consts_f[start_idx], constants, count * sizeof(*constants));
2477 if (TRACE_ON(d3d))
2478 {
2479 for (i = 0; i < count; ++i)
2480 TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2481 }
2482
2483 if (device->recording)
2484 memset(&device->recording->changed.vs_consts_f[start_idx], 1,
2485 count * sizeof(*device->recording->changed.vs_consts_f));
2486 else
2488
2489 return WINED3D_OK;
2490}
2491
2493 unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
2494{
2495 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2496
2497 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2498 device, start_idx, count, constants);
2499
2500 if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
2501 || count > d3d_info->limits.vs_uniform_count - start_idx)
2503
2504 memcpy(constants, &device->state.vs_consts_f[start_idx], count * sizeof(*constants));
2505
2506 return WINED3D_OK;
2507}
2508
2510{
2511 struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL];
2512
2513 TRACE("device %p, shader %p.\n", device, shader);
2514
2515 if (device->recording)
2516 device->recording->changed.pixelShader = TRUE;
2517
2518 if (shader == prev)
2519 return;
2520
2521 if (shader)
2523 device->update_state->shader[WINED3D_SHADER_TYPE_PIXEL] = shader;
2524 if (!device->recording)
2526 if (prev)
2528}
2529
2531{
2532 TRACE("device %p.\n", device);
2533
2534 return device->state.shader[WINED3D_SHADER_TYPE_PIXEL];
2535}
2536
2538{
2539 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2540
2542}
2543
2545{
2546 TRACE("device %p, idx %u.\n", device, idx);
2547
2549}
2550
2553{
2554 TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2555
2557}
2558
2560 UINT idx)
2561{
2562 TRACE("device %p, idx %u.\n", device, idx);
2563
2565}
2566
2568{
2569 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2570
2572}
2573
2575{
2576 TRACE("device %p, idx %u.\n", device, idx);
2577
2579}
2580
2582 unsigned int start_idx, unsigned int count, const BOOL *constants)
2583{
2584 unsigned int i;
2585
2586 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2587 device, start_idx, count, constants);
2588
2589 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2591
2592 if (count > WINED3D_MAX_CONSTS_B - start_idx)
2593 count = WINED3D_MAX_CONSTS_B - start_idx;
2594 memcpy(&device->update_state->ps_consts_b[start_idx], constants, count * sizeof(*constants));
2595 if (TRACE_ON(d3d))
2596 {
2597 for (i = 0; i < count; ++i)
2598 TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2599 }
2600
2601 if (device->recording)
2602 {
2603 for (i = start_idx; i < count + start_idx; ++i)
2604 device->recording->changed.pixelShaderConstantsB |= (1u << i);
2605 }
2606 else
2607 {
2609 }
2610
2611 return WINED3D_OK;
2612}
2613
2615 unsigned int start_idx, unsigned int count, BOOL *constants)
2616{
2617 TRACE("device %p, start_idx %u, count %u,constants %p.\n",
2618 device, start_idx, count, constants);
2619
2620 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
2622
2623 if (count > WINED3D_MAX_CONSTS_B - start_idx)
2624 count = WINED3D_MAX_CONSTS_B - start_idx;
2625 memcpy(constants, &device->state.ps_consts_b[start_idx], count * sizeof(*constants));
2626
2627 return WINED3D_OK;
2628}
2629
2631 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2632{
2633 unsigned int i;
2634
2635 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2636 device, start_idx, count, constants);
2637
2638 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2640
2641 if (count > WINED3D_MAX_CONSTS_I - start_idx)
2642 count = WINED3D_MAX_CONSTS_I - start_idx;
2643 memcpy(&device->update_state->ps_consts_i[start_idx], constants, count * sizeof(*constants));
2644 if (TRACE_ON(d3d))
2645 {
2646 for (i = 0; i < count; ++i)
2647 TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2648 }
2649
2650 if (device->recording)
2651 {
2652 for (i = start_idx; i < count + start_idx; ++i)
2653 device->recording->changed.pixelShaderConstantsI |= (1u << i);
2654 }
2655 else
2656 {
2658 }
2659
2660 return WINED3D_OK;
2661}
2662
2664 unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
2665{
2666 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2667 device, start_idx, count, constants);
2668
2669 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
2671
2672 if (count > WINED3D_MAX_CONSTS_I - start_idx)
2673 count = WINED3D_MAX_CONSTS_I - start_idx;
2674 memcpy(constants, &device->state.ps_consts_i[start_idx], count * sizeof(*constants));
2675
2676 return WINED3D_OK;
2677}
2678
2680 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2681{
2682 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2683 unsigned int i;
2684
2685 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2686 device, start_idx, count, constants);
2687
2688 if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
2689 || count > d3d_info->limits.ps_uniform_count - start_idx)
2691
2692 memcpy(&device->update_state->ps_consts_f[start_idx], constants, count * sizeof(*constants));
2693 if (TRACE_ON(d3d))
2694 {
2695 for (i = 0; i < count; ++i)
2696 TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2697 }
2698
2699 if (device->recording)
2700 memset(&device->recording->changed.ps_consts_f[start_idx], 1,
2701 count * sizeof(*device->recording->changed.ps_consts_f));
2702 else
2704
2705 return WINED3D_OK;
2706}
2707
2709 unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
2710{
2711 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2712
2713 TRACE("device %p, start_idx %u, count %u, constants %p.\n",
2714 device, start_idx, count, constants);
2715
2716 if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
2717 || count > d3d_info->limits.ps_uniform_count - start_idx)
2719
2720 memcpy(constants, &device->state.ps_consts_f[start_idx], count * sizeof(*constants));
2721
2722 return WINED3D_OK;
2723}
2724
2726{
2727 struct wined3d_shader *prev;
2728
2729 TRACE("device %p, shader %p.\n", device, shader);
2730
2731 prev = device->update_state->shader[WINED3D_SHADER_TYPE_HULL];
2732 if (shader == prev)
2733 return;
2734 if (shader)
2736 device->update_state->shader[WINED3D_SHADER_TYPE_HULL] = shader;
2738 if (prev)
2740}
2741
2743{
2744 TRACE("device %p.\n", device);
2745
2746 return device->state.shader[WINED3D_SHADER_TYPE_HULL];
2747}
2748
2750{
2751 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2752
2754}
2755
2757{
2758 TRACE("device %p, idx %u.\n", device, idx);
2759
2761}
2762
2764 unsigned int idx, struct wined3d_shader_resource_view *view)
2765{
2766 TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2767
2769}
2770
2772 unsigned int idx)
2773{
2774 TRACE("device %p, idx %u.\n", device, idx);
2775
2777}
2778
2780 unsigned int idx, struct wined3d_sampler *sampler)
2781{
2782 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2783
2785}
2786
2788{
2789 TRACE("device %p, idx %u.\n", device, idx);
2790
2792}
2793
2795{
2796 struct wined3d_shader *prev;
2797
2798 TRACE("device %p, shader %p.\n", device, shader);
2799
2800 prev = device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN];
2801 if (shader == prev)
2802 return;
2803 if (shader)
2805 device->update_state->shader[WINED3D_SHADER_TYPE_DOMAIN] = shader;
2807 if (prev)
2809}
2810
2812{
2813 TRACE("device %p.\n", device);
2814
2815 return device->state.shader[WINED3D_SHADER_TYPE_DOMAIN];
2816}
2817
2819{
2820 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2821
2823}
2824
2826{
2827 TRACE("device %p, idx %u.\n", device, idx);
2828
2830}
2831
2833 unsigned int idx, struct wined3d_shader_resource_view *view)
2834{
2835 TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2836
2838}
2839
2841 unsigned int idx)
2842{
2843 TRACE("device %p, idx %u.\n", device, idx);
2844
2846}
2847
2849 unsigned int idx, struct wined3d_sampler *sampler)
2850{
2851 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2852
2854}
2855
2857{
2858 TRACE("device %p, idx %u.\n", device, idx);
2859
2861}
2862
2864{
2865 struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
2866
2867 TRACE("device %p, shader %p.\n", device, shader);
2868
2869 if (device->recording || shader == prev)
2870 return;
2871 if (shader)
2873 device->update_state->shader[WINED3D_SHADER_TYPE_GEOMETRY] = shader;
2875 if (prev)
2877}
2878
2880{
2881 TRACE("device %p.\n", device);
2882
2883 return device->state.shader[WINED3D_SHADER_TYPE_GEOMETRY];
2884}
2885
2887{
2888 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2889
2891}
2892
2894{
2895 TRACE("device %p, idx %u.\n", device, idx);
2896
2898}
2899
2902{
2903 TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2904
2906}
2907
2909 UINT idx)
2910{
2911 TRACE("device %p, idx %u.\n", device, idx);
2912
2914}
2915
2917{
2918 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2919
2921}
2922
2924{
2925 TRACE("device %p, idx %u.\n", device, idx);
2926
2928}
2929
2931{
2932 struct wined3d_shader *prev;
2933
2934 TRACE("device %p, shader %p.\n", device, shader);
2935
2936 prev = device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE];
2937 if (device->recording || shader == prev)
2938 return;
2939 if (shader)
2941 device->update_state->shader[WINED3D_SHADER_TYPE_COMPUTE] = shader;
2943 if (prev)
2945}
2946
2948{
2949 TRACE("device %p.\n", device);
2950
2951 return device->state.shader[WINED3D_SHADER_TYPE_COMPUTE];
2952}
2953
2955{
2956 TRACE("device %p, idx %u, buffer %p.\n", device, idx, buffer);
2957
2959}
2960
2962{
2963 TRACE("device %p, idx %u.\n", device, idx);
2964
2966}
2967
2969 unsigned int idx, struct wined3d_shader_resource_view *view)
2970{
2971 TRACE("device %p, idx %u, view %p.\n", device, idx, view);
2972
2974}
2975
2977 unsigned int idx)
2978{
2979 TRACE("device %p, idx %u.\n", device, idx);
2980
2982}
2983
2985 unsigned int idx, struct wined3d_sampler *sampler)
2986{
2987 TRACE("device %p, idx %u, sampler %p.\n", device, idx, sampler);
2988
2990}
2991
2993{
2994 TRACE("device %p, idx %u.\n", device, idx);
2995
2997}
2998
3000 enum wined3d_pipeline pipeline, unsigned int idx, struct wined3d_unordered_access_view *uav,
3001 unsigned int initial_count)
3002{
3003 struct wined3d_unordered_access_view *prev;
3004
3006 {
3007 WARN("Invalid UAV index %u.\n", idx);
3008 return;
3009 }
3010
3011 prev = device->update_state->unordered_access_view[pipeline][idx];
3012 if (uav == prev && initial_count == ~0u)
3013 return;
3014
3015 if (uav)
3017 device->update_state->unordered_access_view[pipeline][idx] = uav;
3018 if (!device->recording)
3019 wined3d_cs_emit_set_unordered_access_view(device->cs, pipeline, idx, uav, initial_count);
3020 if (prev)
3022}
3023
3025 const struct wined3d_device *device, enum wined3d_pipeline pipeline, unsigned int idx)
3026{
3028 {
3029 WARN("Invalid UAV index %u.\n", idx);
3030 return NULL;
3031 }
3032
3033 return device->state.unordered_access_view[pipeline][idx];
3034}
3035
3037 struct wined3d_unordered_access_view *uav, unsigned int initial_count)
3038{
3039 TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count);
3040
3042}
3043
3045 unsigned int idx)
3046{
3047 TRACE("device %p, idx %u.\n", device, idx);
3048
3050}
3051
3053 unsigned int idx, struct wined3d_unordered_access_view *uav, unsigned int initial_count)
3054{
3055 TRACE("device %p, idx %u, uav %p, initial_count %#x.\n", device, idx, uav, initial_count);
3056
3058}
3059
3061 const struct wined3d_device *device, unsigned int idx)
3062{
3063 TRACE("device %p, idx %u.\n", device, idx);
3064
3066}
3067
3068/* Context activation is done by the caller. */
3069#define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3070static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
3072 DWORD DestFVF)
3073{
3074 struct wined3d_matrix mat, proj_mat, view_mat, world_mat;
3075 struct wined3d_map_desc map_desc;
3076 struct wined3d_box box = {0};
3077 struct wined3d_viewport vp;
3078 UINT vertex_size;
3079 unsigned int i;
3080 BYTE *dest_ptr;
3081 BOOL doClip;
3082 DWORD numTextures;
3083 HRESULT hr;
3084
3085 if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL))
3086 {
3087 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3088 }
3089
3090 if (!(stream_info->use_map & (1u << WINED3D_FFP_POSITION)))
3091 {
3092 ERR("Source has no position mask\n");
3094 }
3095
3096 if (device->state.render_states[WINED3D_RS_CLIPPING])
3097 {
3098 static BOOL warned = FALSE;
3099 /*
3100 * The clipping code is not quite correct. Some things need
3101 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3102 * so disable clipping for now.
3103 * (The graphics in Half-Life are broken, and my processvertices
3104 * test crashes with IDirect3DDevice3)
3105 doClip = TRUE;
3106 */
3107 doClip = FALSE;
3108 if(!warned) {
3109 warned = TRUE;
3110 FIXME("Clipping is broken and disabled for now\n");
3111 }
3112 }
3113 else
3114 doClip = FALSE;
3115
3116 vertex_size = get_flexible_vertex_size(DestFVF);
3117 box.left = dwDestIndex * vertex_size;
3118 box.right = box.left + dwCount * vertex_size;
3119 if (FAILED(hr = wined3d_resource_map(&dest->resource, 0, &map_desc, &box, WINED3D_MAP_WRITE)))
3120 {
3121 WARN("Failed to map buffer, hr %#x.\n", hr);
3122 return hr;
3123 }
3124 dest_ptr = map_desc.data;
3125
3129
3130 TRACE("View mat:\n");
3131 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._11, view_mat._12, view_mat._13, view_mat._14);
3132 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._21, view_mat._22, view_mat._23, view_mat._24);
3133 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._31, view_mat._32, view_mat._33, view_mat._34);
3134 TRACE("%.8e %.8e %.8e %.8e\n", view_mat._41, view_mat._42, view_mat._43, view_mat._44);
3135
3136 TRACE("Proj mat:\n");
3137 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._11, proj_mat._12, proj_mat._13, proj_mat._14);
3138 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._21, proj_mat._22, proj_mat._23, proj_mat._24);
3139 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._31, proj_mat._32, proj_mat._33, proj_mat._34);
3140 TRACE("%.8e %.8e %.8e %.8e\n", proj_mat._41, proj_mat._42, proj_mat._43, proj_mat._44);
3141
3142 TRACE("World mat:\n");
3143 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._11, world_mat._12, world_mat._13, world_mat._14);
3144 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._21, world_mat._22, world_mat._23, world_mat._24);
3145 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._31, world_mat._32, world_mat._33, world_mat._34);
3146 TRACE("%.8e %.8e %.8e %.8e\n", world_mat._41, world_mat._42, world_mat._43, world_mat._44);
3147
3148 /* Get the viewport */
3150 TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n",
3151 vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
3152
3153 multiply_matrix(&mat,&view_mat,&world_mat);
3154 multiply_matrix(&mat,&proj_mat,&mat);
3155
3156 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3157
3158 for (i = 0; i < dwCount; i+= 1) {
3159 unsigned int tex_index;
3160
3161 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3162 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3163 /* The position first */
3165 const float *p = (const float *)(element->data.addr + i * element->stride);
3166 float x, y, z, rhw;
3167 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3168
3169 /* Multiplication with world, view and projection matrix. */
3170 x = (p[0] * mat._11) + (p[1] * mat._21) + (p[2] * mat._31) + mat._41;
3171 y = (p[0] * mat._12) + (p[1] * mat._22) + (p[2] * mat._32) + mat._42;
3172 z = (p[0] * mat._13) + (p[1] * mat._23) + (p[2] * mat._33) + mat._43;
3173 rhw = (p[0] * mat._14) + (p[1] * mat._24) + (p[2] * mat._34) + mat._44;
3174
3175 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3176
3177 /* WARNING: The following things are taken from d3d7 and were not yet checked
3178 * against d3d8 or d3d9!
3179 */
3180
3181 /* Clipping conditions: From msdn
3182 *
3183 * A vertex is clipped if it does not match the following requirements
3184 * -rhw < x <= rhw
3185 * -rhw < y <= rhw
3186 * 0 < z <= rhw
3187 * 0 < rhw ( Not in d3d7, but tested in d3d7)
3188 *
3189 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3190 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3191 *
3192 */
3193
3194 if( !doClip ||
3195 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3196 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3197 ( rhw > eps ) ) ) {
3198
3199 /* "Normal" viewport transformation (not clipped)
3200 * 1) The values are divided by rhw
3201 * 2) The y axis is negative, so multiply it with -1
3202 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3203 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3204 * 4) Multiply x with Width/2 and add Width/2
3205 * 5) The same for the height
3206 * 6) Add the viewpoint X and Y to the 2D coordinates and
3207 * The minimum Z value to z
3208 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3209 *
3210 * Well, basically it's simply a linear transformation into viewport
3211 * coordinates
3212 */
3213
3214 x /= rhw;
3215 y /= rhw;
3216 z /= rhw;
3217
3218 y *= -1;
3219
3220 x *= vp.width / 2;
3221 y *= vp.height / 2;
3222 z *= vp.max_z - vp.min_z;
3223
3224 x += vp.width / 2 + vp.x;
3225 y += vp.height / 2 + vp.y;
3226 z += vp.min_z;
3227
3228 rhw = 1 / rhw;
3229 } else {
3230 /* That vertex got clipped
3231 * Contrary to OpenGL it is not dropped completely, it just
3232 * undergoes a different calculation.
3233 */
3234 TRACE("Vertex got clipped\n");
3235 x += rhw;
3236 y += rhw;
3237
3238 x /= 2;
3239 y /= 2;
3240
3241 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3242 * outside of the main vertex buffer memory. That needs some more
3243 * investigation...
3244 */
3245 }
3246
3247 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3248
3249
3250 ( (float *) dest_ptr)[0] = x;
3251 ( (float *) dest_ptr)[1] = y;
3252 ( (float *) dest_ptr)[2] = z;
3253 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3254
3255 dest_ptr += 3 * sizeof(float);
3256
3258 dest_ptr += sizeof(float);
3259 }
3260
3261 if (DestFVF & WINED3DFVF_PSIZE)
3262 dest_ptr += sizeof(DWORD);
3263
3264 if (DestFVF & WINED3DFVF_NORMAL)
3265 {
3267 const float *normal = (const float *)(element->data.addr + i * element->stride);
3268 /* AFAIK this should go into the lighting information */
3269 FIXME("Didn't expect the destination to have a normal\n");
3270 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3271 }
3272
3273 if (DestFVF & WINED3DFVF_DIFFUSE)
3274 {
3276 const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride);
3277 if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE)))
3278 {
3279 static BOOL warned = FALSE;
3280
3281 if(!warned) {
3282 ERR("No diffuse color in source, but destination has one\n");
3283 warned = TRUE;
3284 }
3285
3286 *( (DWORD *) dest_ptr) = 0xffffffff;
3287 dest_ptr += sizeof(DWORD);
3288 }
3289 else
3290 {
3291 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3292 }
3293 }
3294
3295 if (DestFVF & WINED3DFVF_SPECULAR)
3296 {
3297 /* What's the color value in the feedback buffer? */
3299 const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride);
3300 if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR)))
3301 {
3302 static BOOL warned = FALSE;
3303
3304 if(!warned) {
3305 ERR("No specular color in source, but destination has one\n");
3306 warned = TRUE;
3307 }
3308
3309 *(DWORD *)dest_ptr = 0xff000000;
3310 dest_ptr += sizeof(DWORD);
3311 }
3312 else
3313 {
3314 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3315 }
3316 }
3317
3318 for (tex_index = 0; tex_index < numTextures; ++tex_index)
3319 {
3320 const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_TEXCOORD0 + tex_index];
3321 const float *tex_coord = (const float *)(element->data.addr + i * element->stride);
3322 if (!(stream_info->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + tex_index))))
3323 {
3324 ERR("No source texture, but destination requests one\n");
3325 dest_ptr += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3326 }
3327 else
3328 {
3329 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3330 }
3331 }
3332 }
3333
3334 wined3d_resource_unmap(&dest->resource, 0);
3335
3336 return WINED3D_OK;
3337}
3338#undef copy_and_next
3339
3341 UINT src_start_idx, UINT dst_idx, UINT vertex_count, struct wined3d_buffer *dst_buffer,
3342 const struct wined3d_vertex_declaration *declaration, DWORD flags, DWORD dst_fvf)
3343{
3344 struct wined3d_state *state = &device->state;
3346 struct wined3d_resource *resource;
3347 struct wined3d_box box = {0};
3348 struct wined3d_shader *vs;
3349 unsigned int i;
3350 HRESULT hr;
3351 WORD map;
3352
3353 TRACE("device %p, src_start_idx %u, dst_idx %u, vertex_count %u, "
3354 "dst_buffer %p, declaration %p, flags %#x, dst_fvf %#x.\n",
3355 device, src_start_idx, dst_idx, vertex_count,
3356 dst_buffer, declaration, flags, dst_fvf);
3357
3358 if (declaration)
3359 FIXME("Output vertex declaration not implemented yet.\n");
3360
3363 wined3d_stream_info_from_declaration(&stream_info, state, &device->adapter->gl_info, &device->adapter->d3d_info);
3365
3366 /* We can't convert FROM a VBO, and vertex buffers used to source into
3367 * process_vertices() are unlikely to ever be used for drawing. Release
3368 * VBOs in those buffers and fix up the stream_info structure.
3369 *
3370 * Also apply the start index. */
3371 for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
3372 {
3374 struct wined3d_map_desc map_desc;
3375
3376 if (!(map & 1))
3377 continue;
3378
3379 e = &stream_info.elements[i];
3380 resource = &state->streams[e->stream_idx].buffer->resource;
3381 box.left = src_start_idx * e->stride;
3382 box.right = box.left + vertex_count * e->stride;
3384 ERR("Failed to map resource.\n");
3385 e->data.buffer_object = 0;
3386 e->data.addr += (ULONG_PTR)map_desc.data;
3387 }
3388
3390 &stream_info, dst_buffer, flags, dst_fvf);
3391
3392 for (i = 0, map = stream_info.use_map; map; map >>= 1, ++i)
3393 {
3394 if (!(map & 1))
3395 continue;
3396
3397 resource = &state->streams[stream_info.elements[i].stream_idx].buffer->resource;
3399 ERR("Failed to unmap resource.\n");
3400 }
3401
3402 return hr;
3403}
3404
3407{
3408 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
3410
3411 TRACE("device %p, stage %u, state %s, value %#x.\n",
3413
3415 {
3416 WARN("Invalid state %#x passed.\n", state);
3417 return;
3418 }
3419
3420 if (stage >= d3d_info->limits.ffp_blend_stages)
3421 {
3422 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
3423 stage, d3d_info->limits.ffp_blend_stages - 1);
3424 return;
3425 }
3426
3427 old_value = device->update_state->texture_states[stage][state];
3428 device->update_state->texture_states[stage][state] = value;
3429
3430 if (device->recording)
3431 {
3432 TRACE("Recording... not performing anything.\n");
3433 device->recording->changed.textureState[stage] |= 1u << state;
3434 return;
3435 }
3436
3437 /* Checked after the assignments to allow proper stateblock recording. */
3438 if (old_value == value)
3439 {
3440 TRACE("Application is setting the old value over, nothing to do.\n");
3441 return;
3442 }
3443
3445}
3446
3449{
3450 TRACE("device %p, stage %u, state %s.\n",
3452
3454 {
3455 WARN("Invalid state %#x passed.\n", state);
3456 return 0;
3457 }
3458
3459 return device->state.texture_states[stage][state];
3460}
3461
3463 UINT stage, struct wined3d_texture *texture)
3464{
3465 struct wined3d_texture *prev;
3466
3467 TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
3468
3471
3472 /* Windows accepts overflowing this array... we do not. */
3473 if (stage >= ARRAY_SIZE(device->state.textures))
3474 {
3475 WARN("Ignoring invalid stage %u.\n", stage);
3476 return WINED3D_OK;
3477 }
3478
3479 if (texture && texture->resource.usage & WINED3DUSAGE_SCRATCH)
3480 {
3481 WARN("Rejecting attempt to set scratch texture.\n");
3483 }
3484
3485 if (device->recording)
3486 device->recording->changed.textures |= 1u << stage;
3487
3488 prev = device->update_state->textures[stage];
3489 TRACE("Previous texture %p.\n", prev);
3490
3491 if (texture == prev)
3492 {
3493 TRACE("App is setting the same texture again, nothing to do.\n");
3494 return WINED3D_OK;
3495 }
3496
3497 TRACE("Setting new texture to %p.\n", texture);
3498 device->update_state->textures[stage] = texture;
3499
3500 if (texture)
3502 if (!device->recording)
3504 if (prev)
3506
3507 return WINED3D_OK;
3508}
3509
3511{
3512 TRACE("device %p, stage %u.\n", device, stage);
3513
3516
3517 if (stage >= ARRAY_SIZE(device->state.textures))
3518 {
3519 WARN("Ignoring invalid stage %u.\n", stage);
3520 return NULL; /* Windows accepts overflowing this array ... we do not. */
3521 }
3522
3523 return device->state.textures[stage];
3524}
3525
3527{
3528 HRESULT hr;
3529
3530 TRACE("device %p, caps %p.\n", device, caps);
3531
3532 hr = wined3d_get_device_caps(device->wined3d, device->adapter->ordinal,
3533 device->create_parms.device_type, caps);
3534
3536 caps->MaxVertexBlendMatrixIndex = 255;
3537
3538 return hr;
3539}
3540
3542 struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
3543{
3544 struct wined3d_swapchain *swapchain;
3545
3546 TRACE("device %p, swapchain_idx %u, mode %p, rotation %p.\n",
3547 device, swapchain_idx, mode, rotation);
3548
3549 if (!(swapchain = wined3d_device_get_swapchain(device, swapchain_idx)))
3551
3552 return wined3d_swapchain_get_display_mode(swapchain, mode, rotation);
3553}
3554
3556{
3557 struct wined3d_stateblock *stateblock;
3558 HRESULT hr;
3559
3560 TRACE("device %p.\n", device);
3561
3562 if (device->recording)
3564
3566 if (FAILED(hr))
3567 return hr;
3568
3569 device->recording = stateblock;
3570 device->update_state = &stateblock->state;
3571
3572 TRACE("Recording stateblock %p.\n", stateblock);
3573
3574 return WINED3D_OK;
3575}
3576
3578 struct wined3d_stateblock **stateblock)
3579{
3580 struct wined3d_stateblock *object = device->recording;
3581
3582 TRACE("device %p, stateblock %p.\n", device, stateblock);
3583
3584 if (!device->recording)
3585 {
3586 WARN("Not recording.\n");
3587 *stateblock = NULL;
3589 }
3590
3592
3593 *stateblock = object;
3594 device->recording = NULL;
3595 device->update_state = &device->state;
3596
3597 TRACE("Returning stateblock %p.\n", *stateblock);
3598
3599 return WINED3D_OK;
3600}
3601
3603{
3604 /* At the moment we have no need for any functionality at the beginning
3605 * of a scene. */
3606 TRACE("device %p.\n", device);
3607
3608 if (device->inScene)
3609 {
3610 WARN("Already in scene, returning WINED3DERR_INVALIDCALL.\n");
3612 }
3613 device->inScene = TRUE;
3614 return WINED3D_OK;
3615}
3616
3618{
3619 TRACE("device %p.\n", device);
3620
3621 if (!device->inScene)
3622 {
3623 WARN("Not in scene, returning WINED3DERR_INVALIDCALL.\n");
3625 }
3626
3628
3629 device->inScene = FALSE;
3630 return WINED3D_OK;
3631}
3632
3634 const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
3635{
3636 TRACE("device %p, rect_count %u, rects %p, flags %#x, color %s, depth %.8e, stencil %u.\n",
3637 device, rect_count, rects, flags, debug_color(color), depth, stencil);
3638
3639 if (!rect_count && rects)
3640 {
3641 WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects);
3642 return WINED3D_OK;
3643 }
3644
3646 {
3647 struct wined3d_rendertarget_view *ds = device->fb.depth_stencil;
3648 if (!ds)
3649 {
3650 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
3651 /* TODO: What about depth stencil buffers without stencil bits? */
3653 }
3654 else if (flags & WINED3DCLEAR_TARGET)
3655 {
3656 if (ds->width < device->fb.render_targets[0]->width
3657 || ds->height < device->fb.render_targets[0]->height)
3658 {
3659 WARN("Silently ignoring depth and target clear with mismatching sizes\n");
3660 return WINED3D_OK;
3661 }
3662 }
3663 }
3664
3665 wined3d_cs_emit_clear(device->cs, rect_count, rects, flags, color, depth, stencil);
3666
3667 return WINED3D_OK;
3668}
3669
3671 struct wined3d_query *predicate, BOOL value)
3672{
3673 struct wined3d_query *prev;
3674
3675 TRACE("device %p, predicate %p, value %#x.\n", device, predicate, value);
3676
3677 prev = device->update_state->predicate;
3678 if (predicate)
3679 {
3680 FIXME("Predicated rendering not implemented.\n");
3681 wined3d_query_incref(predicate);
3682 }
3683 device->update_state->predicate = predicate;
3684 device->update_state->predicate_value = value;
3685 if (!device->recording)
3687 if (prev)
3689}
3690
3692{
3693 TRACE("device %p, value %p.\n", device, value);
3694
3695 if (value)
3696 *value = device->state.predicate_value;
3697 return device->state.predicate;
3698}
3699
3701 unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z)
3702{
3703 TRACE("device %p, group_count_x %u, group_count_y %u, group_count_z %u.\n",
3704 device, group_count_x, group_count_y, group_count_z);
3705
3706 wined3d_cs_emit_dispatch(device->cs, group_count_x, group_count_y, group_count_z);
3707}
3708
3710 struct wined3d_buffer *buffer, unsigned int offset)
3711{
3712 TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
3713
3715}
3716
3718 enum wined3d_primitive_type primitive_type, unsigned int patch_vertex_count)
3719{
3720 TRACE("device %p, primitive_type %s, patch_vertex_count %u.\n",
3721 device, debug_d3dprimitivetype(primitive_type), patch_vertex_count);
3722
3723 device->state.gl_primitive_type = gl_primitive_type_from_d3d(primitive_type);
3724 device->state.gl_patch_vertices = patch_vertex_count;
3725}
3726
3728 enum wined3d_primitive_type *primitive_type, unsigned int *patch_vertex_count)
3729{
3730 TRACE("device %p, primitive_type %p, patch_vertex_count %p.\n",
3731 device, primitive_type, patch_vertex_count);
3732
3733 *primitive_type = d3d_primitive_type_from_gl(device->state.gl_primitive_type);
3734 if (patch_vertex_count)
3735 *patch_vertex_count = device->state.gl_patch_vertices;
3736
3737 TRACE("Returning %s.\n", debug_d3dprimitivetype(*primitive_type));
3738}
3739