mirror of
https://github.com/electron/electron.git
synced 2026-01-10 07:58:08 -05:00
fix: visual artifacts while resizing on Windows (#49138)
Manual backports of: - crrev.com/c/7129658 - crrev.com/c/7210913 - crrev.com/c/7115438
This commit is contained in:
@@ -144,3 +144,6 @@ expose_referrerscriptinfo_hostdefinedoptionsindex.patch
|
||||
chore_disable_protocol_handler_dcheck.patch
|
||||
fix_release_mouse_buttons_on_focus_loss_on_wayland.patch
|
||||
viz_fix_visual_artifacts_due_to_resizing_root_render_pass_with_dcomp.patch
|
||||
viz_do_not_overallocate_surface_on_initial_render.patch
|
||||
viz_create_isbufferqueuesupportedandenabled.patch
|
||||
viz_fix_visual_artifacts_while_resizing_window_with_dcomp.patch
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 3 Dec 2025 17:10:02 +0100
|
||||
Subject: viz: Create IsBufferQueueSupportedAndEnabled()
|
||||
|
||||
Manual backport of crrev.com/c/7210913
|
||||
|
||||
Bug: 457463689
|
||||
Change-Id: I31bbaa6b5d79697c6bb5e1fc6738f6ea5a937b4f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7210913
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Commit-Queue: David Sanders <dsanders11@ucsbalum.com>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1553190}
|
||||
|
||||
diff --git a/components/viz/service/display/output_surface.cc b/components/viz/service/display/output_surface.cc
|
||||
index ff795eb057ac64f40aa842fec8e053d12f57f538..71287614c627d39f8d019889498205ab3eff2a69 100644
|
||||
--- a/components/viz/service/display/output_surface.cc
|
||||
+++ b/components/viz/service/display/output_surface.cc
|
||||
@@ -21,6 +21,16 @@
|
||||
|
||||
namespace viz {
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+// Use BufferQueue for the primary plane instead of a DXGI swap chain or DComp
|
||||
+// surface.
|
||||
+BASE_FEATURE(kBufferQueue, base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+#endif
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
OutputSurface::Capabilities::Capabilities() = default;
|
||||
OutputSurface::Capabilities::~Capabilities() = default;
|
||||
OutputSurface::Capabilities::Capabilities(const Capabilities& capabilities) =
|
||||
@@ -94,6 +104,12 @@ bool IsDelegatedCompositingSupportedAndEnabled(
|
||||
// Ensure we check the feature flag iff the feature is supported.
|
||||
return features::IsDelegatedCompositingEnabled();
|
||||
}
|
||||
+
|
||||
+bool IsBufferQueueSupportedAndEnabled(
|
||||
+ OutputSurface::DCSupportLevel support_level) {
|
||||
+ return support_level >= OutputSurface::DCSupportLevel::kDCompDynamicTexture &&
|
||||
+ base::FeatureList::IsEnabled(kBufferQueue);
|
||||
+}
|
||||
#endif
|
||||
|
||||
} // namespace viz
|
||||
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h
|
||||
index 25306ab6e18a266efdc329e4ddd81f5303033f4c..589f4c10dad9c807c9e3ce7baba63795b629435b 100644
|
||||
--- a/components/viz/service/display/output_surface.h
|
||||
+++ b/components/viz/service/display/output_surface.h
|
||||
@@ -307,6 +307,9 @@ class VIZ_SERVICE_EXPORT OutputSurface {
|
||||
// `features::IsDelegatedCompositingEnabled()`.
|
||||
bool IsDelegatedCompositingSupportedAndEnabled(
|
||||
OutputSurface::DCSupportLevel support_level);
|
||||
+
|
||||
+bool IsBufferQueueSupportedAndEnabled(
|
||||
+ OutputSurface::DCSupportLevel support_level);
|
||||
#endif
|
||||
|
||||
} // namespace viz
|
||||
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
|
||||
index e34e15dda13a183568fc3e186d3b89da1e828ad4..9b9a4c02c975799fe42b04f0d5b680274d28b09e 100644
|
||||
--- a/components/viz/service/display/skia_renderer.cc
|
||||
+++ b/components/viz/service/display/skia_renderer.cc
|
||||
@@ -121,12 +121,6 @@ namespace {
|
||||
BASE_FEATURE(kDumpWithoutCrashingOnMissingRenderPassBacking,
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
-#if BUILDFLAG(IS_WIN)
|
||||
-// Use BufferQueue for the primary plane instead of a DXGI swap chain or DComp
|
||||
-// surface.
|
||||
-BASE_FEATURE(kBufferQueue, base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
-#endif
|
||||
-
|
||||
// Smallest unit that impacts anti-aliasing output. We use this to determine
|
||||
// when an exterior edge (with AA) has been clipped (no AA). The specific value
|
||||
// was chosen to match that used by gl_renderer.
|
||||
@@ -992,10 +986,8 @@ SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
|
||||
|
||||
// It's possible to use BufferQueue with DComp textures, so we can optionally
|
||||
// enable it behind a feature flag.
|
||||
- const bool want_buffer_queue =
|
||||
- output_surface_->capabilities().dc_support_level >=
|
||||
- OutputSurface::DCSupportLevel::kDCompDynamicTexture &&
|
||||
- base::FeatureList::IsEnabled(kBufferQueue);
|
||||
+ const bool want_buffer_queue = IsBufferQueueSupportedAndEnabled(
|
||||
+ output_surface_->capabilities().dc_support_level);
|
||||
#else
|
||||
const bool want_buffer_queue = true;
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 3 Dec 2025 17:08:55 +0100
|
||||
Subject: viz: Do not overallocate surface on initial render
|
||||
|
||||
Manual backport of crrev.com/c/7129658
|
||||
|
||||
Change-Id: I0baa5865dbe66efc7b0f3f793c8e89cdc6aaa0b6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7129658
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1544293}
|
||||
|
||||
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
|
||||
index c03a4b3db61371021a94128f698126b5fef2f577..01abf5d36e2e117acf6f9cdc91307c9ac5616453 100644
|
||||
--- a/components/viz/service/display/direct_renderer.cc
|
||||
+++ b/components/viz/service/display/direct_renderer.cc
|
||||
@@ -1081,10 +1081,13 @@ gfx::Size DirectRenderer::CalculateTextureSizeForRenderPass(
|
||||
// buffer area and number of reallocations to quantify the trade-off.
|
||||
gfx::Size DirectRenderer::CalculateSizeForOutputSurface(
|
||||
const gfx::Size& requested_viewport_size) {
|
||||
+ const gfx::Size surface_size = surface_size_for_swap_buffers();
|
||||
+
|
||||
// We're not able to clip back buffers if output surface does not support
|
||||
- // clipping.
|
||||
- if (requested_viewport_size == surface_size_for_swap_buffers() ||
|
||||
+ // clipping. We don't round on the initial frame when a window is first shown.
|
||||
+ if (requested_viewport_size == surface_size ||
|
||||
!output_surface_->capabilities().supports_viewporter ||
|
||||
+ surface_size.IsZero() ||
|
||||
settings_->dont_round_texture_sizes_for_pixel_tests) {
|
||||
device_viewport_size_ = requested_viewport_size;
|
||||
return requested_viewport_size;
|
||||
@@ -1102,8 +1105,8 @@ gfx::Size DirectRenderer::CalculateSizeForOutputSurface(
|
||||
// allows backings to be more easily reused during a resize operation.
|
||||
const int request_width = requested_viewport_size.width();
|
||||
const int request_height = requested_viewport_size.height();
|
||||
- int surface_width = surface_size_for_swap_buffers().width();
|
||||
- int surface_height = surface_size_for_swap_buffers().height();
|
||||
+ int surface_width = surface_size.width();
|
||||
+ int surface_height = surface_size.height();
|
||||
constexpr int multiple = 256;
|
||||
|
||||
// If |request_width| or |request_height| is already a multiple of |multiple|,
|
||||
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 3 Dec 2025 17:42:58 +0100
|
||||
Subject: viz: Fix visual artifacts while resizing window with DComp
|
||||
|
||||
Manual backport of crrev.com/c/7115438
|
||||
|
||||
Bug: 457463689
|
||||
Change-Id: I9c684effe15e0b112ae533faa243e5a035e9c875
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7115438
|
||||
Commit-Queue: David Sanders <dsanders11@ucsbalum.com>
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1553192}
|
||||
|
||||
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
|
||||
index 01abf5d36e2e117acf6f9cdc91307c9ac5616453..7e45d9ea46d0d4095169daf748e20c98db21969d 100644
|
||||
--- a/components/viz/service/display/direct_renderer.cc
|
||||
+++ b/components/viz/service/display/direct_renderer.cc
|
||||
@@ -243,6 +243,31 @@ void DirectRenderer::DrawFrame(
|
||||
current_frame()->device_viewport_size = device_viewport_size;
|
||||
current_frame()->display_color_spaces = display_color_spaces;
|
||||
|
||||
+ gfx::Size surface_resource_size =
|
||||
+ CalculateSizeForOutputSurface(device_viewport_size);
|
||||
+
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+ if (output_surface_->capabilities().clear_drawn_areas_outside_viewport &&
|
||||
+ device_viewport_size != surface_resource_size) {
|
||||
+ // On Windows with DirectComposition, we cannot synchronize the swap chain
|
||||
+ // |Present| and the DComp |Commit| calls to take effect at the same time.
|
||||
+ // (Both take effect asynchronously.) Hence, presenting a frame and changing
|
||||
+ // the DComp layer clip rect can happen at different times. This can lead to
|
||||
+ // ugly visual artifacts while resizing the window because it can reveal
|
||||
+ // areas of the surface that are outside the viewport (crbug.com/457463689).
|
||||
+ // To prevent those artifacts, we clear areas outside of the viewport with a
|
||||
+ // transparent color. Transparency is expensive, so we use it only while
|
||||
+ // resizing.
|
||||
+ // This line gives us a transparent image format and triggers the background
|
||||
+ // to be cleared in |SkiaRenderer::ClearFramebuffer|.
|
||||
+ root_render_pass->has_transparent_background = true;
|
||||
+ // Redraw and swap the whole surface.
|
||||
+ root_render_pass->output_rect = gfx::Rect(surface_resource_size);
|
||||
+ current_frame()->root_damage_rect = gfx::Rect(surface_resource_size);
|
||||
+ current_frame()->device_viewport_size = surface_resource_size;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
output_surface_->SetNeedsMeasureNextDrawLatency();
|
||||
BeginDrawingFrame();
|
||||
|
||||
@@ -274,8 +299,6 @@ void DirectRenderer::DrawFrame(
|
||||
current_frame()->display_color_spaces.GetOutputBufferFormat(
|
||||
current_frame()->root_render_pass->content_color_usage,
|
||||
frame_has_alpha));
|
||||
- gfx::Size surface_resource_size =
|
||||
- CalculateSizeForOutputSurface(device_viewport_size);
|
||||
if (overlay_processor_) {
|
||||
// Display transform and viewport size are needed for overlay validator on
|
||||
// Android SurfaceControl, and viewport size is need on Windows. These need
|
||||
@@ -397,8 +420,10 @@ void DirectRenderer::DrawFrame(
|
||||
|
||||
// If we need to redraw the frame, the whole output should be considered
|
||||
// damaged.
|
||||
- if (needs_full_frame_redraw)
|
||||
- current_frame()->root_damage_rect = gfx::Rect(device_viewport_size);
|
||||
+ if (needs_full_frame_redraw) {
|
||||
+ current_frame()->root_damage_rect =
|
||||
+ gfx::Rect(current_frame()->device_viewport_size);
|
||||
+ }
|
||||
|
||||
if (!skip_drawing_root_render_pass) {
|
||||
DrawRenderPassAndExecuteCopyRequests(root_render_pass);
|
||||
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h
|
||||
index 589f4c10dad9c807c9e3ce7baba63795b629435b..641bbfc732c88141ddd929a4c334360462259ee4 100644
|
||||
--- a/components/viz/service/display/output_surface.h
|
||||
+++ b/components/viz/service/display/output_surface.h
|
||||
@@ -106,6 +106,11 @@ class VIZ_SERVICE_EXPORT OutputSurface {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Whether this OutputSurface supports direct composition layers.
|
||||
DCSupportLevel dc_support_level = DCSupportLevel::kNone;
|
||||
+ // Whether to 1) clear all drawn areas outside the viewport with a
|
||||
+ // transparent background color when drawing a frame and 2) swap them. This
|
||||
+ // is necessary if the surface clip rect can get out of sync with the
|
||||
+ // viewport size (e.g., due to a race condition).
|
||||
+ bool clear_drawn_areas_outside_viewport = false;
|
||||
#endif
|
||||
// Whether this OutputSurface should skip DrawAndSwap(). This is true for
|
||||
// the unified display on Chrome OS. All drawing is handled by the physical
|
||||
diff --git a/components/viz/service/display_embedder/skia_output_device_dcomp.cc b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
index 7ac9ea1cdc4416a7af8dc2a75404cbc15be6cfad..8e027d1382c5d639c1e114b8e25b6cea3af3445d 100644
|
||||
--- a/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
+++ b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
@@ -39,10 +39,8 @@
|
||||
namespace viz {
|
||||
|
||||
namespace {
|
||||
-// With DirectComposition, resize surface based on root render pass size to
|
||||
-// avoid gutter which shows stale pixels.
|
||||
-BASE_FEATURE(kDirectCompositionResizeBasedOnRootSurface,
|
||||
- base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
+// Apply fixes for crbug.com/457463689.
|
||||
+BASE_FEATURE(kDirectCompositionResizeFixes, base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
base::TimeTicks g_last_reshape_failure = base::TimeTicks();
|
||||
|
||||
@@ -161,7 +159,14 @@ SkiaOutputDeviceDComp::SkiaOutputDeviceDComp(
|
||||
capabilities_.supports_viewporter = presenter_->SupportsViewporter();
|
||||
capabilities_.supports_non_backed_solid_color_overlays = true;
|
||||
capabilities_.resize_based_on_root_surface =
|
||||
- base::FeatureList::IsEnabled(kDirectCompositionResizeBasedOnRootSurface);
|
||||
+ base::FeatureList::IsEnabled(kDirectCompositionResizeFixes);
|
||||
+ // With delegated compositing or a buffer queue, |Present| and |Commit| are
|
||||
+ // synchronized and the clear is not needed.
|
||||
+ capabilities_.clear_drawn_areas_outside_viewport =
|
||||
+ base::FeatureList::IsEnabled(kDirectCompositionResizeFixes) &&
|
||||
+ !IsDelegatedCompositingSupportedAndEnabled(
|
||||
+ capabilities_.dc_support_level) &&
|
||||
+ !IsBufferQueueSupportedAndEnabled(capabilities_.dc_support_level);
|
||||
|
||||
DCHECK(context_state_);
|
||||
DCHECK(context_state_->gr_context() ||
|
||||
Reference in New Issue
Block a user