Skip to content
Permalink
Browse files

Combined de-jelly effect merge for M78

This patch contains de-jelly logic landed so far in M79.

Note that de-jelly logic is behind multiple levels of safeguards:
- All features are disabled unless a command line flag
  "--enable-de-jelly" or a system property "enable_de_jelly_for_chrome"
  is set. Neither of these is set by default.
- A kill-switch is present which can disable this code even if the
  above flag / property is enabled.
- All code is force disabled for WebView at all times.

This includes:
https://chromium-review.googlesource.com/c/chromium/src/+/1859585
https://chromium-review.googlesource.com/c/chromium/src/+/1861096
https://chromium-review.googlesource.com/c/chromium/src/+/1837115
https://chromium-review.googlesource.com/c/chromium/src/+/1819495
https://chromium-review.googlesource.com/c/chromium/src/+/1819641
https://chromium-review.googlesource.com/c/chromium/src/+/1827254
https://chromium-review.googlesource.com/c/chromium/src/+/1811458
https://chromium-review.googlesource.com/c/chromium/src/+/1810317

Bug: 995965
Change-Id: I1713bba46890c5dd0453dea0dc8c4003e9c9001b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1863352
Reviewed-by: Victor Miura <vmiura@chromium.org>
Cr-Commit-Position: refs/branch-heads/3904@{#774}
Cr-Branched-From: 675968a-refs/heads/master@{#693954}
  • Loading branch information
Eric Karl
Eric Karl committed Oct 15, 2019
1 parent e47f2d3 commit 86e7d17008ec1215c36a958025cb188eb2fb9d4a
Showing with 989 additions and 5 deletions.
  1. +1 −0 android_webview/BUILD.gn
  2. +3 −0 android_webview/lib/aw_main_delegate.cc
  3. +2 −0 cc/BUILD.gn
  4. +4 −0 cc/layers/render_surface_impl.cc
  5. +181 −0 cc/trees/de_jelly_state.cc
  6. +54 −0 cc/trees/de_jelly_state.h
  7. +8 −0 cc/trees/draw_property_utils.cc
  8. +13 −0 cc/trees/layer_tree_host_impl.cc
  9. +4 −0 cc/trees/layer_tree_host_impl.h
  10. +3 −0 cc/trees/layer_tree_settings.h
  11. +1 −0 cc/trees/property_tree.h
  12. +1 −0 chrome/android/BUILD.gn
  13. +1 −0 chrome/android/DEPS
  14. +8 −0 chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
  15. +4 −0 chrome/browser/about_flags.cc
  16. +5 −0 chrome/browser/flag-metadata.json
  17. +7 −0 chrome/browser/flag_descriptions.cc
  18. +3 −0 chrome/browser/flag_descriptions.h
  19. +24 −1 components/viz/common/BUILD.gn
  20. +59 −0 components/viz/common/display/de_jelly.cc
  21. +35 −0 components/viz/common/display/de_jelly.h
  22. +5 −0 components/viz/common/features.cc
  23. +1 −0 components/viz/common/features.h
  24. +16 −0 components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java
  25. +152 −0 components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java
  26. +3 −0 components/viz/common/quads/shared_quad_state.h
  27. +7 −0 components/viz/common/switches.cc
  28. +2 −0 components/viz/common/switches.h
  29. +8 −0 components/viz/service/display/display.cc
  30. +1 −0 components/viz/service/display/display_scheduler.h
  31. +299 −4 components/viz/service/display/surface_aggregator.cc
  32. +47 −0 components/viz/service/display/surface_aggregator.h
  33. +2 −0 content/browser/gpu/gpu_process_host.cc
  34. +1 −0 content/browser/renderer_host/render_process_host_impl.cc
  35. +10 −0 content/renderer/render_widget.cc
  36. +9 −0 services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
  37. +4 −0 services/viz/public/mojom/compositing/shared_quad_state.mojom
  38. +1 −0 tools/metrics/histograms/enums.xml
@@ -898,6 +898,7 @@ android_library("android_webview_java") {
"//components/variations:load_seed_result_enum_java",
"//components/variations/android:variations_java",
"//components/version_info/android:version_constants_java",
"//components/viz/common:common_java",
"//content/public/android:content_java",
"//device/gamepad:java",
"//mojo/public/java:system_java",
@@ -217,6 +217,9 @@ bool AwMainDelegate::BasicStartupComplete(int* exit_code) {
// TODO(https://crbug.com/963653): SmsReceiver is not yet supported on
// WebView.
features.DisableIfNotSet(::features::kSmsReceiver);

// De-jelly is never supported on WebView.
features.EnableIfNotSet(::features::kDisableDeJelly);
}

android_webview::RegisterPathProvider();
@@ -282,6 +282,8 @@ cc_component("cc") {
"trees/compositor_mode.h",
"trees/damage_tracker.cc",
"trees/damage_tracker.h",
"trees/de_jelly_state.cc",
"trees/de_jelly_state.h",
"trees/debug_rect_history.cc",
"trees/debug_rect_history.h",
"trees/draw_property_utils.cc",
@@ -20,6 +20,7 @@
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/occlusion.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/display/de_jelly.h"
#include "components/viz/common/quads/content_draw_quad_base.h"
#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/render_pass.h"
@@ -255,6 +256,9 @@ gfx::Rect RenderSurfaceImpl::CalculateClippedAccumulatedContentRect() {
} else {
clipped_accumulated_rect_in_target_space = clip_rect();
}
if (layer_tree_impl_->settings().allow_de_jelly_effect) {
clipped_accumulated_rect_in_target_space.Inset(0, -viz::MaxDeJellyHeight());
}
clipped_accumulated_rect_in_target_space.Intersect(
accumulated_rect_in_target_space);

@@ -0,0 +1,181 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/trees/de_jelly_state.h"

#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/display/de_jelly.h"

namespace cc {

DeJellyState::DeJellyState() = default;
DeJellyState::~DeJellyState() = default;

void DeJellyState::AdvanceFrame(LayerTreeImpl* layer_tree_impl) {
if (!layer_tree_impl->settings().allow_de_jelly_effect)
return;

should_de_jelly_ = false;

// Move the |new_transforms_| from the previous draw into
// |previous_transforms_|.
std::swap(previous_transforms_, new_transforms_);
new_transforms_.clear();

// Make sure we have an active scroll node. Otherwise we won't perform any
// de-jelly.
ScrollNode* current_scroll =
layer_tree_impl->property_trees()->scroll_tree.Node(
layer_tree_impl->property_trees()
->scroll_tree.currently_scrolling_node());
if (!current_scroll) {
new_scroll_node_transform_.reset();
return;
}

scroll_transform_node_ = current_scroll->transform_id;

// Check to make sure the ToScreen transform of our scroll node is not a
// complex transform (doesn't work well with de-jelly). Also make sure the
// scale is not changing.
base::Optional<gfx::Transform> previous_scroll_transform =
new_scroll_node_transform_;
new_scroll_node_transform_ =
layer_tree_impl->property_trees()->transform_tree.ToScreen(
current_scroll->transform_id);
if (!previous_scroll_transform ||
!previous_scroll_transform->IsScaleOrTranslation() ||
!new_scroll_node_transform_->IsScaleOrTranslation() ||
new_scroll_node_transform_->Scale2d() !=
previous_scroll_transform->Scale2d()) {
return;
}

// Compute the fallback movement of a scrolling element based purely on the
// scroll offset of the currently scrolling node.
float previous_scroll_offset = scroll_offset_;
scroll_offset_ = layer_tree_impl->property_trees()
->transform_tree.Node(scroll_transform_node_)
->scroll_offset.y();
fallback_delta_y_ = scroll_offset_ - previous_scroll_offset;
gfx::Vector3dF vector(0, fallback_delta_y_, 0);
new_scroll_node_transform_->TransformVector(&vector);
fallback_delta_y_ = vector.y();

// Don't attempt de-jelly while the omnibox is transitioning in or out. There
// is no correct way to handle this.
float top_controls_shown_ratio =
layer_tree_impl->top_controls_shown_ratio()->Current(
true /* is_active_tree */);
if (top_controls_shown_ratio != 0.0f && top_controls_shown_ratio != 1.0f)
return;

// We've passed our initial checks, allow de-jelly in UpdateSharedQuadState.
should_de_jelly_ = true;
}

void DeJellyState::UpdateSharedQuadState(LayerTreeImpl* layer_tree_impl,
int transform_id,
viz::RenderPass* target_render_pass) {
if (!should_de_jelly_)
return;
DCHECK(layer_tree_impl->settings().allow_de_jelly_effect);

viz::SharedQuadState* state =
target_render_pass->shared_quad_state_list.back();
state->de_jelly_delta_y = 0.0f;

// Check if |transform_id| is a child of our |scroll_transform_node_|
// and if it scrolls (is not sticky or fixed).
bool does_not_scroll = false;
auto node_id = transform_id;
while (node_id != scroll_transform_node_ && node_id != kInvalidNodeId) {
auto* current_node =
layer_tree_impl->property_trees()->transform_tree.Node(node_id);

// Position fixed.
if (current_node->moved_by_outer_viewport_bounds_delta_y) {
does_not_scroll = true;
break;
}
// Position sticky.
if (current_node->sticky_position_constraint_id > -1) {
const StickyPositionNodeData* sticky_data =
layer_tree_impl->property_trees()
->transform_tree.GetStickyPositionData(node_id);
if (sticky_data &&
sticky_data->total_containing_block_sticky_offset.y() > 0.0f) {
does_not_scroll = true;
break;
}
}

node_id = current_node->parent_id;
}
does_not_scroll |= node_id == kInvalidNodeId;
if (does_not_scroll)
return;

// Get the current node's ToScreen transform.
gfx::Transform transform =
layer_tree_impl->property_trees()->transform_tree.ToScreen(transform_id);
new_transforms_[transform_id] = transform;

// Get the previous transform (if any).
const auto& found = previous_transforms_.find(transform_id);

float delta_y = 0.0f;
if (found == previous_transforms_.end()) {
delta_y = fallback_delta_y_;
} else {
// Calculate the delta of point (0, 0) from the previous frame.
gfx::Transform previous_transform = found->second;
gfx::PointF new_point(0, 0);
transform.TransformPoint(&new_point);
gfx::PointF old_point(0, 0);
previous_transform.TransformPoint(&old_point);
delta_y = old_point.y() - new_point.y();
}

if (delta_y == 0.0f) {
return;
}

// To minimize jarring visible effects, we de-jelly differently at
// different magnitudes of |delta_y|. This is controlled by three variables:
// kLinearDeJellyStart, kFixedDeJellyStart, kZeroDeJellyStart.
// _____________
// | | _/| |
// de_jelly_delta_y | | _/ | |
// |_____|_/ | |_______________
// +----------------------------------------
// kLinear kFixed kZero
//
const float kLinearDeJellyStart = 2.0f;
const float kFixedDeJellyStart =
viz::MaxDeJellyHeight() + kLinearDeJellyStart;
const float kZeroDeJellyStart = 100.0f + kLinearDeJellyStart;
float sign = std::abs(delta_y) / delta_y;
float de_jelly_delta_y = std::abs(delta_y);
if (de_jelly_delta_y > kZeroDeJellyStart) {
de_jelly_delta_y = 0.0f;
} else if (de_jelly_delta_y > kFixedDeJellyStart) {
de_jelly_delta_y = kFixedDeJellyStart - kLinearDeJellyStart;
} else if (de_jelly_delta_y > kLinearDeJellyStart) {
de_jelly_delta_y = std::max(0.0f, de_jelly_delta_y - kLinearDeJellyStart);
} else {
de_jelly_delta_y = 0.0f;
}
// Re-apply the sign.
de_jelly_delta_y *= sign;
if (de_jelly_delta_y == 0.0f) {
return;
}

state->de_jelly_delta_y = de_jelly_delta_y;
}

} // namespace cc
@@ -0,0 +1,54 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_TREES_DE_JELLY_STATE_H_
#define CC_TREES_DE_JELLY_STATE_H_

#include <map>

#include "base/containers/flat_map.h"
#include "base/no_destructor.h"
#include "base/optional.h"
#include "cc/cc_export.h"
#include "ui/gfx/transform.h"

namespace viz {
class SharedQuadState;
class RenderPass;
} // namespace viz

namespace cc {
class LayerTreeImpl;

// Helper class which tracks the movement of layers and renderpasses
// and computes the |de_jelly_delta_y| for their SharedQuadState.
class CC_EXPORT DeJellyState {
public:
DeJellyState();
~DeJellyState();

// Called once per frame to move tracking structure to the next frame and
// determine if we should apply de-jelly at all.
void AdvanceFrame(LayerTreeImpl* layer_tree_impl);

// Populates |de_jelly_delta_y| for the most recent SharedQuadState on
// |target_render_pass|.
void UpdateSharedQuadState(LayerTreeImpl* layer_tree_impl,
int transform_id,
viz::RenderPass* target_render_pass);

private:
bool should_de_jelly_ = false;
int scroll_transform_node_ = 0;
float scroll_offset_ = 0;
float fallback_delta_y_ = 0;

base::Optional<gfx::Transform> new_scroll_node_transform_;
std::map<int, gfx::Transform> previous_transforms_;
std::map<int, gfx::Transform> new_transforms_;
};

} // namespace cc

#endif // CC_TREES_DE_JELLY_STATE_H_
@@ -21,6 +21,7 @@
#include "cc/trees/property_tree_builder.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/display/de_jelly.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {
@@ -643,6 +644,13 @@ static gfx::Rect LayerVisibleRect(PropertyTrees* property_trees,
clip_in_layer_space.Offset(-layer->offset_to_transform_parent());

gfx::Rect visible_rect = ToEnclosingClipRect(clip_in_layer_space);
if (layer->layer_tree_impl()->settings().allow_de_jelly_effect) {
float padding_amount = viz::MaxDeJellyHeight();
if (layer->IsAffectedByPageScale()) {
padding_amount /= layer->layer_tree_impl()->current_page_scale_factor();
}
visible_rect.Inset(0.0f, -padding_amount);
}
visible_rect.Intersect(layer_content_rect);
return visible_rect;
}
@@ -1236,6 +1236,9 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
active_tree()->property_trees()->effect_tree.HasCopyRequests();
bool have_missing_animated_tiles = false;

// Advance our de-jelly state. This is a no-op if de-jelly is not active.
de_jelly_state_.AdvanceFrame(active_tree_.get());

for (EffectTreeLayerListIterator it(active_tree());
it.state() != EffectTreeLayerListIterator::State::END; ++it) {
auto target_render_pass_id = it.target_render_surface()->id();
@@ -1259,6 +1262,11 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
if (render_surface->contributes_to_drawn_surface()) {
render_surface->AppendQuads(draw_mode, target_render_pass,
&append_quads_data);
if (settings_.allow_de_jelly_effect) {
de_jelly_state_.UpdateSharedQuadState(
active_tree_.get(), render_surface->TransformTreeIndex(),
target_render_pass);
}
}
} else if (it.state() == EffectTreeLayerListIterator::State::LAYER) {
LayerImpl* layer = it.current_layer();
@@ -1270,6 +1278,11 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
frame->may_contain_video = true;

layer->AppendQuads(target_render_pass, &append_quads_data);
if (settings_.allow_de_jelly_effect) {
de_jelly_state_.UpdateSharedQuadState(active_tree_.get(),
layer->transform_tree_index(),
target_render_pass);
}
}

rendering_stats_instrumentation_->AddVisibleContentArea(
@@ -40,6 +40,7 @@
#include "cc/tiles/image_decode_cache.h"
#include "cc/tiles/tile_manager.h"
#include "cc/trees/animated_paint_worklet_tracker.h"
#include "cc/trees/de_jelly_state.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_mutator.h"
@@ -1277,6 +1278,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// invalidating PaintWorklets as the property values change.
AnimatedPaintWorkletTracker paint_worklet_tracker_;

// Helper for de-jelly logic.
DeJellyState de_jelly_state_;

// Must be the last member to ensure this is destroyed first in the
// destruction order and invalidates all weak pointers.
base::WeakPtrFactory<LayerTreeHostImpl> weak_factory_{this};
@@ -172,6 +172,9 @@ class CC_EXPORT LayerTreeSettings {
// When false, we do not check for occlusion and all quads are drawn.
// Defaults to true.
bool enable_occlusion = true;

// Whether experimental de-jelly effect is allowed.
bool allow_de_jelly_effect = false;
};

} // namespace cc
@@ -401,6 +401,7 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
int CurrentlyScrollingNodeId() const;
#endif
void set_currently_scrolling_node(int scroll_node_id);
int currently_scrolling_node() const { return currently_scrolling_node_id_; }
gfx::Transform ScreenSpaceTransform(int scroll_node_id) const;

gfx::Vector2dF ClampScrollToMaxScrollOffset(ScrollNode* node, LayerTreeImpl*);
@@ -335,6 +335,7 @@ android_library("chrome_java") {
"//components/url_formatter/android:url_formatter_java",
"//components/variations/android:variations_java",
"//components/version_info/android:version_constants_java",
"//components/viz/common:common_java",
"//components/viz/service:service_java",
"//content/public/android:content_java",
"//device/gamepad:java",
@@ -8,6 +8,7 @@ include_rules = [
"+components/signin/core/browser/android",
"+components/signin/public/identity_manager/android",
"+components/spellcheck/browser",
"+components/viz/common/java",
"+jni",
"+media/base/android/java",
"+services/media_session/public",

0 comments on commit 86e7d17

Please sign in to comment.
You can’t perform that action at this time.