Apply throttling to occluded frame sinks.
cc::OcclusionTracker calculates and marks the occlusion states for each layer and this occlusion information is used to skip appending quads if a layer will not be drawn. These occluded layers will not make into the CompositorFrame, however, there's no action taken to the surfaces that are occluded so the frame sinks continue to submit CompositorFrames at full rate. This CL takes advantage of the occlusion information and uses it to mark the frame sinks that will not draw as qualified for throttling. ChromeOS ash then throttle the frame sinks accordingly. This CL is an effort to improve ChromeOS login/lock screen performance. There might be other scenarios that could benefit from this CL. This CL will throttle all active browser windows behind the lock screen if EnableCompositingBasedThrottling feature is enabled. Usually an occluded window is detected by aura::WindowOcclusionTracker, however aura::WindowOcclusionTracker only tracks aura::Window, the lock screen uses a solid color layer through WallpaperView for the purpose of occlusion and this occlusion is not detectable by aura::WindowOcclusionTracker, but is caught in cc. The performance comparison between with and with out this CL, locally tested on Nami is: - Two windows running webgl aquarium measures at 30% cpu usage when logged in. The cpu usage drops to 20% without throttling and 15% with throttling when locked. - One maximized window running webgl aquarium measures at 15% cpu usage when logged in. The cpu usage doesn't drop without throttling and drops to 11% with throttling applied. Bug: 1193824 Change-Id: I8bfc987663446bceb13ce248c4d52782cbdc47d3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2919945 Commit-Queue: Jun Liu <yjliu@chromium.org> Reviewed-by: kylechar <kylechar@chromium.org> Cr-Commit-Position: refs/heads/master@{#889509}
This commit is contained in:
@ -1290,6 +1290,9 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
|
||||
layer->transform_tree_index(),
|
||||
target_render_pass);
|
||||
}
|
||||
} else {
|
||||
if (settings_.enable_compositing_based_throttling)
|
||||
throttle_decider_.ProcessLayerNotToDraw(layer);
|
||||
}
|
||||
|
||||
rendering_stats_instrumentation_->AddVisibleContentArea(
|
||||
|
@ -865,6 +865,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
|
||||
return pending_raster_queries_.get();
|
||||
}
|
||||
|
||||
base::flat_set<viz::FrameSinkId> GetFrameSinksToThrottleForTesting() const {
|
||||
return throttle_decider_.ids();
|
||||
}
|
||||
|
||||
protected:
|
||||
LayerTreeHostImpl(
|
||||
const LayerTreeSettings& settings,
|
||||
|
@ -891,6 +891,16 @@ class CommitToPendingTreeLayerTreeHostImplTest : public LayerTreeHostImplTest {
|
||||
}
|
||||
};
|
||||
|
||||
class OccludedSurfaceThrottlingLayerTreeHostImplTest
|
||||
: public LayerTreeHostImplTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
LayerTreeSettings settings = DefaultSettings();
|
||||
settings.enable_compositing_based_throttling = true;
|
||||
CreateHostImpl(settings, CreateLayerTreeFrameSink());
|
||||
}
|
||||
};
|
||||
|
||||
// A test fixture for new animation timelines tests.
|
||||
class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest {
|
||||
public:
|
||||
@ -18083,6 +18093,33 @@ TEST_F(UnifiedScrollingTest, CompositedWithSquashedLayerMutatesTransform) {
|
||||
ScrollEnd();
|
||||
}
|
||||
|
||||
// Verifies that when a surface layer is occluded, its frame sink id will be
|
||||
// marked as qualified for throttling.
|
||||
TEST_F(OccludedSurfaceThrottlingLayerTreeHostImplTest,
|
||||
ThrottleOccludedSurface) {
|
||||
LayerTreeImpl* tree = host_impl_->active_tree();
|
||||
gfx::Rect viewport_rect(0, 0, 800, 600);
|
||||
auto* root = SetupRootLayer<LayerImpl>(tree, viewport_rect.size());
|
||||
|
||||
auto* occluded = AddLayer<SurfaceLayerImpl>(tree);
|
||||
occluded->SetBounds(gfx::Size(400, 300));
|
||||
occluded->SetDrawsContent(true);
|
||||
viz::SurfaceId start = MakeSurfaceId(viz::FrameSinkId(1, 2), 1);
|
||||
viz::SurfaceId end = MakeSurfaceId(viz::FrameSinkId(3, 4), 1);
|
||||
occluded->SetRange(viz::SurfaceRange(start, end), 2u);
|
||||
CopyProperties(root, occluded);
|
||||
|
||||
auto* occluder = AddLayer<SolidColorLayerImpl>(tree);
|
||||
occluder->SetBounds(gfx::Size(400, 400));
|
||||
occluder->SetDrawsContent(true);
|
||||
occluder->SetContentsOpaque(true);
|
||||
CopyProperties(root, occluder);
|
||||
|
||||
DrawFrame();
|
||||
EXPECT_EQ(host_impl_->GetFrameSinksToThrottleForTesting(),
|
||||
base::flat_set<viz::FrameSinkId>{end.frame_sink_id()});
|
||||
}
|
||||
|
||||
TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestSimple) {
|
||||
SetupDefaultRootLayer(gfx::Size(100, 100));
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cc/layers/surface_layer_impl.h"
|
||||
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
|
||||
#include "components/viz/common/quads/surface_draw_quad.h"
|
||||
#include "components/viz/common/surfaces/surface_range.h"
|
||||
@ -86,6 +87,14 @@ void ThrottleDecider::ProcessRenderPass(
|
||||
id_to_pass_map_.emplace(render_pass.id, &render_pass);
|
||||
}
|
||||
|
||||
void ThrottleDecider::ProcessLayerNotToDraw(const LayerImpl* layer) {
|
||||
if (layer->is_surface_layer()) {
|
||||
const auto* surface_layer = static_cast<const SurfaceLayerImpl*>(layer);
|
||||
if (surface_layer->range().IsValid())
|
||||
ids_.insert(surface_layer->range().end().frame_sink_id());
|
||||
}
|
||||
}
|
||||
|
||||
bool ThrottleDecider::HasThrottlingChanged() const {
|
||||
return ids_ != last_ids_;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "components/viz/common/surfaces/frame_sink_id.h"
|
||||
|
||||
namespace cc {
|
||||
class LayerImpl;
|
||||
|
||||
// This class is used to decide if any frame sinks in a render pass list
|
||||
// satisfies the compositing-based criteria to be throttled.
|
||||
@ -30,6 +31,9 @@ class CC_EXPORT ThrottleDecider {
|
||||
// intersection calculation of surface/quad rects are confined to the render
|
||||
// pass's constituent quads.
|
||||
void ProcessRenderPass(const viz::CompositorRenderPass& render_pass);
|
||||
// Process a layer that will not draw. This is only relevant for surface
|
||||
// layers and checks if the embedded frame sink is qualified for throttling.
|
||||
void ProcessLayerNotToDraw(const LayerImpl* layer);
|
||||
bool HasThrottlingChanged() const;
|
||||
const base::flat_set<viz::FrameSinkId>& ids() const { return ids_; }
|
||||
|
||||
|
Reference in New Issue
Block a user