Commit a34ce7c7 authored by Maggie Chen's avatar Maggie Chen Committed by Commit Bot

Add a switch for the new overlay damage method on Windows

A new feature switch DirectCompositionUseOverlayDamageList is added to
enable the new method that removes the overlay damage from the
root damage to get the final optimized damage rect.

This CL also adds a new histogram
GPU.DirectComposition.DCLayer.OverlayCount which records the total
number of overlays we are going to present in the DC overlay processor.

Bug:1117235

Change-Id: I1fb97d8b4fd96270ff6447b63ad86785d60c2eeb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2416966
Commit-Queue: Maggie Chen <magchen@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#813071}
parent 6eb0eb37
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <limits> #include <limits>
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
#include "components/viz/service/display/display_resource_provider.h" #include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/overlay_processor_interface.h" #include "components/viz/service/display/overlay_processor_interface.h"
#include "gpu/GLES2/gl2extchromium.h" #include "gpu/GLES2/gl2extchromium.h"
#include "gpu/config/gpu_finch_features.h"
#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/rect_conversions.h"
...@@ -71,7 +73,8 @@ DCLayerResult ValidateYUVQuad( ...@@ -71,7 +73,8 @@ DCLayerResult ValidateYUVQuad(
const YUVVideoDrawQuad* quad, const YUVVideoDrawQuad* quad,
const std::vector<gfx::Rect>& backdrop_filter_rects, const std::vector<gfx::Rect>& backdrop_filter_rects,
bool has_overlay_support, bool has_overlay_support,
int current_frame_processed_overlay_count, int allowed_yuv_overlay_count,
int processed_yuv_overlay_count,
DisplayResourceProvider* resource_provider) { DisplayResourceProvider* resource_provider) {
// Note: Do not override this value based on base::Feature values. It is the // Note: Do not override this value based on base::Feature values. It is the
// result after the GPU blocklist has been consulted. // result after the GPU blocklist has been consulted.
...@@ -97,7 +100,7 @@ DCLayerResult ValidateYUVQuad( ...@@ -97,7 +100,7 @@ DCLayerResult ValidateYUVQuad(
return DC_LAYER_FAILED_COMPLEX_TRANSFORM; return DC_LAYER_FAILED_COMPLEX_TRANSFORM;
} }
if (current_frame_processed_overlay_count > 0) if (processed_yuv_overlay_count >= allowed_yuv_overlay_count)
return DC_LAYER_FAILED_TOO_MANY_OVERLAYS; return DC_LAYER_FAILED_TOO_MANY_OVERLAYS;
// Rounded corner on overlays are not supported. // Rounded corner on overlays are not supported.
...@@ -320,8 +323,13 @@ DCLayerOverlay::~DCLayerOverlay() = default; ...@@ -320,8 +323,13 @@ DCLayerOverlay::~DCLayerOverlay() = default;
DCLayerOverlayProcessor::DCLayerOverlayProcessor( DCLayerOverlayProcessor::DCLayerOverlayProcessor(
const DebugRendererSettings* debug_settings, const DebugRendererSettings* debug_settings,
int allowed_yuv_overlay_count,
bool skip_initialization_for_testing) bool skip_initialization_for_testing)
: has_overlay_support_(skip_initialization_for_testing), : has_overlay_support_(skip_initialization_for_testing),
use_overlay_damage_list_(base::FeatureList::IsEnabled(
features::kDirectCompositionUseOverlayDamageList)),
allowed_yuv_overlay_count_(
use_overlay_damage_list_ ? allowed_yuv_overlay_count : 1),
debug_settings_(debug_settings), debug_settings_(debug_settings),
viz_task_runner_(skip_initialization_for_testing viz_task_runner_(skip_initialization_for_testing
? nullptr ? nullptr
...@@ -406,6 +414,7 @@ void DCLayerOverlayProcessor::Process( ...@@ -406,6 +414,7 @@ void DCLayerOverlayProcessor::Process(
gfx::Rect* damage_rect, gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays) { DCLayerOverlayList* dc_layer_overlays) {
gfx::Rect this_frame_underlay_rect; gfx::Rect this_frame_underlay_rect;
processed_yuv_overlay_count_ = 0;
// Which render passes have backdrop filters. // Which render passes have backdrop filters.
base::flat_set<AggregatedRenderPassId> render_pass_has_backdrop_filters; base::flat_set<AggregatedRenderPassId> render_pass_has_backdrop_filters;
...@@ -451,11 +460,13 @@ void DCLayerOverlayProcessor::Process( ...@@ -451,11 +460,13 @@ void DCLayerOverlayProcessor::Process(
DCLayerResult result; DCLayerResult result;
switch (it->material) { switch (it->material) {
case DrawQuad::Material::kYuvVideoContent: case DrawQuad::Material::kYuvVideoContent:
result = result = ValidateYUVQuad(
ValidateYUVQuad(YUVVideoDrawQuad::MaterialCast(*it), YUVVideoDrawQuad::MaterialCast(*it), backdrop_filter_rects,
backdrop_filter_rects, has_overlay_support_, has_overlay_support_, allowed_yuv_overlay_count_,
candidate_index_list.size(), resource_provider); processed_yuv_overlay_count_, resource_provider);
yuv_quads_in_quad_list++; yuv_quads_in_quad_list++;
if (result == DC_LAYER_SUCCESS)
processed_yuv_overlay_count_++;
break; break;
case DrawQuad::Material::kTextureContent: case DrawQuad::Material::kTextureContent:
result = ValidateTextureQuad(TextureDrawQuad::MaterialCast(*it), result = ValidateTextureQuad(TextureDrawQuad::MaterialCast(*it),
...@@ -483,11 +494,17 @@ void DCLayerOverlayProcessor::Process( ...@@ -483,11 +494,17 @@ void DCLayerOverlayProcessor::Process(
candidate_index_list.push_back(index); candidate_index_list.push_back(index);
} }
// A YUV quad might be rejected later due to not allowed as an underlay.
// Recount the YUV overlays when they are added to the overlay list
// successfully.
processed_yuv_overlay_count_ = 0;
// TODO(magchen@): Revisit this code if allowed_yuv_overlay_count_ > 1.
// We might not save power if there are more than one videos and only one is // We might not save power if there are more than one videos and only one is
// promoted to overlay. Skip overlays for this frame unless there are // promoted to overlay. Skip overlays for this frame unless there are
// protected video or texture overlays. // protected video or texture overlays.
if (candidate_index_list.size() > 0 && yuv_quads_in_quad_list > 1 && if (candidate_index_list.size() > 0 &&
yuv_quads_in_quad_list > allowed_yuv_overlay_count_ &&
!has_protected_video_or_texture_overlays) { !has_protected_video_or_texture_overlays) {
candidate_index_list.clear(); candidate_index_list.clear();
// In this case, there is only one candidate in the list. // In this case, there is only one candidate in the list.
...@@ -516,6 +533,12 @@ void DCLayerOverlayProcessor::Process( ...@@ -516,6 +533,12 @@ void DCLayerOverlayProcessor::Process(
// skipped if they're not underlay compatible. // skipped if they're not underlay compatible.
const bool requires_overlay = IsProtectedVideo(it); const bool requires_overlay = IsProtectedVideo(it);
// TODO(magchen@): Since we reject underlays here, the max number of YUV
// overlays we can promote might not be accurate. We should allow all YUV
// quads to be put into candidate_index_list, but only
// |allowed_yuv_overlay_count_| YUV quads should be promoted to
// overlays/underlays from that list.
// Skip quad if it's an underlay and underlays are not allowed. // Skip quad if it's an underlay and underlays are not allowed.
if (!is_overlay && !requires_overlay) { if (!is_overlay && !requires_overlay) {
DCLayerResult result = IsUnderlayAllowed(it); DCLayerResult result = IsUnderlayAllowed(it);
...@@ -539,16 +562,23 @@ void DCLayerOverlayProcessor::Process( ...@@ -539,16 +562,23 @@ void DCLayerOverlayProcessor::Process(
// found in this frame, the previous overlay rects would have been handled // found in this frame, the previous overlay rects would have been handled
// above and |previous_frame_overlay_rect_union_| becomes empty. // above and |previous_frame_overlay_rect_union_| becomes empty.
damage_rect->Union(previous_frame_overlay_rect_union_); damage_rect->Union(previous_frame_overlay_rect_union_);
damage_rect->Intersect(gfx::ToEnclosingRect(display_rect));
previous_frame_overlay_rect_union_ = current_frame_overlay_rect_union_; previous_frame_overlay_rect_union_ = current_frame_overlay_rect_union_;
current_frame_overlay_rect_union_ = gfx::Rect(); current_frame_overlay_rect_union_ = gfx::Rect();
previous_frame_processed_overlay_count_ = previous_frame_processed_overlay_count_ =
current_frame_processed_overlay_count_; current_frame_processed_overlay_count_;
current_frame_processed_overlay_count_ = 0; current_frame_processed_overlay_count_ = 0;
damage_rect->Intersect(gfx::ToEnclosingRect(display_rect));
previous_display_rect_ = display_rect; previous_display_rect_ = display_rect;
previous_frame_underlay_rect_ = this_frame_underlay_rect; previous_frame_underlay_rect_ = this_frame_underlay_rect;
if (!dc_layer_overlays->empty()) {
base::UmaHistogramExactLinear(
"GPU.DirectComposition.DCLayer.YUVOverlayCount",
/*sample=*/processed_yuv_overlay_count_,
/*value_max=*/10);
}
if (debug_settings_->show_dc_layer_debug_borders && if (debug_settings_->show_dc_layer_debug_borders &&
dc_layer_overlays->size() > 0) { dc_layer_overlays->size() > 0) {
InsertDebugBorderDrawQuad(dc_layer_overlays, root_render_pass, display_rect, InsertDebugBorderDrawQuad(dc_layer_overlays, root_render_pass, display_rect,
...@@ -576,6 +606,7 @@ void DCLayerOverlayProcessor::UpdateDCLayerOverlays( ...@@ -576,6 +606,7 @@ void DCLayerOverlayProcessor::UpdateDCLayerOverlays(
case DrawQuad::Material::kYuvVideoContent: case DrawQuad::Material::kYuvVideoContent:
FromYUVQuad(YUVVideoDrawQuad::MaterialCast(*it), FromYUVQuad(YUVVideoDrawQuad::MaterialCast(*it),
render_pass->transform_to_root_target, &dc_layer); render_pass->transform_to_root_target, &dc_layer);
processed_yuv_overlay_count_++;
break; break;
case DrawQuad::Material::kTextureContent: case DrawQuad::Material::kTextureContent:
FromTextureQuad(TextureDrawQuad::MaterialCast(*it), FromTextureQuad(TextureDrawQuad::MaterialCast(*it),
...@@ -624,7 +655,6 @@ void DCLayerOverlayProcessor::UpdateDCLayerOverlays( ...@@ -624,7 +655,6 @@ void DCLayerOverlayProcessor::UpdateDCLayerOverlays(
dc_layer_overlays->push_back(dc_layer); dc_layer_overlays->push_back(dc_layer);
// Only allow one overlay unless it's hardware protected video.
current_frame_processed_overlay_count_++; current_frame_processed_overlay_count_++;
} }
......
...@@ -79,8 +79,14 @@ class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor ...@@ -79,8 +79,14 @@ class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor
public: public:
// When |skip_initialization_for_testing| is true, object will be isolated // When |skip_initialization_for_testing| is true, object will be isolated
// for unit tests. // for unit tests.
// allowed_yuv_overlay_count will be limited to 1 if
// |use_overlay_damage_list_| is not supported. This new method produces an
// empty root damage rect when the overlay quads are the only damages in the
// frames. If |use_overlay_damage_list_| is false, we should not allowed more
// than one YUV overlays since non-empty damage rect won't save any power.
explicit DCLayerOverlayProcessor( explicit DCLayerOverlayProcessor(
const DebugRendererSettings* debug_settings, const DebugRendererSettings* debug_settings,
int allowed_yuv_overlay_count,
bool skip_initialization_for_testing = false); bool skip_initialization_for_testing = false);
virtual ~DCLayerOverlayProcessor(); virtual ~DCLayerOverlayProcessor();
...@@ -137,6 +143,11 @@ class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor ...@@ -137,6 +143,11 @@ class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor
gfx::Rect* damage_rect); gfx::Rect* damage_rect);
bool has_overlay_support_; bool has_overlay_support_;
const bool use_overlay_damage_list_;
// TODO(magchen@): We are going to support more than one YUV overlay.
const int allowed_yuv_overlay_count_;
int processed_yuv_overlay_count_ = 0;
// Reference to the global viz singleton. // Reference to the global viz singleton.
const DebugRendererSettings* const debug_settings_; const DebugRendererSettings* const debug_settings_;
......
...@@ -2523,7 +2523,9 @@ TEST_F(MockOutputSurfaceTest, BackbufferDiscard) { ...@@ -2523,7 +2523,9 @@ TEST_F(MockOutputSurfaceTest, BackbufferDiscard) {
class MockDCLayerOverlayProcessor : public DCLayerOverlayProcessor { class MockDCLayerOverlayProcessor : public DCLayerOverlayProcessor {
public: public:
MockDCLayerOverlayProcessor() MockDCLayerOverlayProcessor()
: DCLayerOverlayProcessor(&debug_settings_, true) {} : DCLayerOverlayProcessor(&debug_settings_,
/*allowed_yuv_overlay_count=*/1,
true) {}
~MockDCLayerOverlayProcessor() override = default; ~MockDCLayerOverlayProcessor() override = default;
MOCK_METHOD5(Process, MOCK_METHOD5(Process,
void(DisplayResourceProvider* resource_provider, void(DisplayResourceProvider* resource_provider,
...@@ -3669,7 +3671,8 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) { ...@@ -3669,7 +3671,8 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
auto processor = std::make_unique<OverlayProcessorWin>( auto processor = std::make_unique<OverlayProcessorWin>(
output_surface.get(), output_surface.get(),
std::make_unique<DCLayerOverlayProcessor>(&debug_settings_, true)); std::make_unique<DCLayerOverlayProcessor>(
&debug_settings_, /*allowed_yuv_overlay_count=*/1, true));
RendererSettings settings; RendererSettings settings;
settings.partial_swap_enabled = true; settings.partial_swap_enabled = true;
......
...@@ -101,10 +101,11 @@ class OverlayOutputSurface : public OutputSurface { ...@@ -101,10 +101,11 @@ class OverlayOutputSurface : public OutputSurface {
class DCTestOverlayProcessor : public OverlayProcessorWin { class DCTestOverlayProcessor : public OverlayProcessorWin {
public: public:
explicit DCTestOverlayProcessor(OutputSurface* output_surface) explicit DCTestOverlayProcessor(OutputSurface* output_surface)
: OverlayProcessorWin( : OverlayProcessorWin(output_surface,
output_surface, std::make_unique<DCLayerOverlayProcessor>(
std::make_unique<DCLayerOverlayProcessor>(&debug_settings_, true)) { &debug_settings_,
} /*allowed_yuv_overlay_count=*/1,
true)) {}
DebugRendererSettings debug_settings_; DebugRendererSettings debug_settings_;
}; };
......
...@@ -92,8 +92,8 @@ OverlayProcessorInterface::CreateOverlayProcessor( ...@@ -92,8 +92,8 @@ OverlayProcessorInterface::CreateOverlayProcessor(
enable_ca_overlay); enable_ca_overlay);
#elif defined(OS_WIN) #elif defined(OS_WIN)
return std::make_unique<OverlayProcessorWin>( return std::make_unique<OverlayProcessorWin>(
output_surface, output_surface, std::make_unique<DCLayerOverlayProcessor>(
std::make_unique<DCLayerOverlayProcessor>(debug_settings)); debug_settings, /*allowed_yuv_overlay_count=*/1));
#elif defined(USE_OZONE) #elif defined(USE_OZONE)
if (!features::IsUsingOzonePlatform()) if (!features::IsUsingOzonePlatform())
return std::make_unique<OverlayProcessorStub>(); return std::make_unique<OverlayProcessorStub>();
......
...@@ -52,6 +52,11 @@ const base::Feature kDefaultEnableOopRasterization{ ...@@ -52,6 +52,11 @@ const base::Feature kDefaultEnableOopRasterization{
// Use a high priority for GPU process on Windows. // Use a high priority for GPU process on Windows.
const base::Feature kGpuProcessHighPriorityWin{ const base::Feature kGpuProcessHighPriorityWin{
"GpuProcessHighPriorityWin", base::FEATURE_ENABLED_BY_DEFAULT}; "GpuProcessHighPriorityWin", base::FEATURE_ENABLED_BY_DEFAULT};
// Compute the root damage rect from the surface damage list for overlays on
// Windows.
const base::Feature kDirectCompositionUseOverlayDamageList{
"DirectCompositionUseOverlayDamageList", base::FEATURE_ENABLED_BY_DEFAULT};
#endif #endif
// Use ThreadPriority::DISPLAY for GPU main, viz compositor and IO threads. // Use ThreadPriority::DISPLAY for GPU main, viz compositor and IO threads.
......
...@@ -28,6 +28,8 @@ GPU_EXPORT extern const base::Feature kDefaultEnableOopRasterization; ...@@ -28,6 +28,8 @@ GPU_EXPORT extern const base::Feature kDefaultEnableOopRasterization;
#if defined(OS_WIN) #if defined(OS_WIN)
GPU_EXPORT extern const base::Feature kGpuProcessHighPriorityWin; GPU_EXPORT extern const base::Feature kGpuProcessHighPriorityWin;
GPU_EXPORT extern const base::Feature kDirectCompositionUseOverlayDamageList;
#endif #endif
GPU_EXPORT extern const base::Feature kGpuUseDisplayThreadPriority; GPU_EXPORT extern const base::Feature kGpuUseDisplayThreadPriority;
......
...@@ -366,6 +366,17 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -366,6 +366,17 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="GPU.DirectComposition.DCLayer.YUVOverlayCount"
units="overlays" expires_after="2021-03-15">
<owner>magchen@chromium.org</owner>
<owner>zmo@chromium.org</owner>
<summary>
The number of YUV overlays we are going to present in each frame if the
number is not 0. Recorded when the overlay processor is called for drawing a
frame.
</summary>
</histogram>
<histogram name="GPU.DirectComposition.DCLayerResult.Texture" <histogram name="GPU.DirectComposition.DCLayerResult.Texture"
enum="DCLayerResult" expires_after="2020-12-31"> enum="DCLayerResult" expires_after="2020-12-31">
<owner>sunnyps@chromium.org</owner> <owner>sunnyps@chromium.org</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment