From 935f2672bad41a2b49761f887a53cae0c4901b53 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Thu, 9 Jan 2020 19:52:23 -0800 Subject: [PATCH 1/4] Add more profile markers --- flow/layers/child_scene_layer.cc | 1 + flow/layers/clip_path_layer.cc | 9 ++++++++- flow/layers/clip_rect_layer.cc | 9 ++++++++- flow/layers/clip_rrect_layer.cc | 9 ++++++++- flow/layers/picture_layer.cc | 5 +++++ flow/layers/texture_layer.cc | 5 +++++ flow/layers/transform_layer.cc | 3 +++ 7 files changed, 38 insertions(+), 3 deletions(-) diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 10b5a277db575..524878817483e 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -42,6 +42,7 @@ void ChildSceneLayer::Paint(PaintContext& context) const { } void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) { + TRACE_EVENT0("flutter", "ChildSceneLayer::UpdateScene"); FML_DCHECK(needs_system_composite()); auto* view_holder = ViewHolder::FromId(layer_id_); diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index 3d420657bf079..b85b48fb082b6 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -18,10 +18,14 @@ ClipPathLayer::ClipPathLayer(const SkPath& clip_path, Clip clip_behavior) } void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "ClipPathLayer::Preroll"); + SkRect previous_cull_rect = context->cull_rect; SkRect clip_path_bounds = clip_path_.getBounds(); children_inside_clip_ = context->cull_rect.intersect(clip_path_bounds); if (children_inside_clip_) { + TRACE_EVENT_INSTANT0("flutter", "children inside clip rect"); + Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); context->mutators_stack.PushClipPath(clip_path_); @@ -39,6 +43,7 @@ void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { #if defined(OS_FUCHSIA) void ClipPathLayer::UpdateScene(SceneUpdateContext& context) { + TRACE_EVENT0("flutter", "ClipPathLayer::UpdateScene"); FML_DCHECK(needs_system_composite()); // TODO(liyuqian): respect clip_behavior_ @@ -52,8 +57,10 @@ void ClipPathLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipPathLayer::Paint"); FML_DCHECK(needs_painting()); - if (!children_inside_clip_) + if (!children_inside_clip_) { + TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping"); return; + } SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipPath(clip_path_, diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index af6c490f27a7d..cc58e721c7f75 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -12,9 +12,13 @@ ClipRectLayer::ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior) } void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "ClipRectLayer::Preroll"); + SkRect previous_cull_rect = context->cull_rect; children_inside_clip_ = context->cull_rect.intersect(clip_rect_); if (children_inside_clip_) { + TRACE_EVENT_INSTANT0("flutter", "children inside clip rect"); + Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); context->mutators_stack.PushClipRect(clip_rect_); @@ -32,6 +36,7 @@ void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { #if defined(OS_FUCHSIA) void ClipRectLayer::UpdateScene(SceneUpdateContext& context) { + TRACE_EVENT0("flutter", "ClipRectLayer::UpdateScene"); FML_DCHECK(needs_system_composite()); // TODO(liyuqian): respect clip_behavior_ @@ -45,8 +50,10 @@ void ClipRectLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipRectLayer::Paint"); FML_DCHECK(needs_painting()); - if (!children_inside_clip_) + if (!children_inside_clip_) { + TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping"); return; + } SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index d640b8b47171f..054379a4088bc 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -12,10 +12,14 @@ ClipRRectLayer::ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior) } void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "ClipRRectLayer::Preroll"); + SkRect previous_cull_rect = context->cull_rect; SkRect clip_rrect_bounds = clip_rrect_.getBounds(); children_inside_clip_ = context->cull_rect.intersect(clip_rrect_bounds); if (children_inside_clip_) { + TRACE_EVENT_INSTANT0("flutter", "children inside clip rect"); + Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); context->mutators_stack.PushClipRRect(clip_rrect_); @@ -33,6 +37,7 @@ void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { #if defined(OS_FUCHSIA) void ClipRRectLayer::UpdateScene(SceneUpdateContext& context) { + TRACE_EVENT0("flutter", "ClipRRectLayer::UpdateScene"); FML_DCHECK(needs_system_composite()); // TODO(liyuqian): respect clip_behavior_ @@ -46,8 +51,10 @@ void ClipRRectLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipRRectLayer::Paint"); FML_DCHECK(needs_painting()); - if (!children_inside_clip_) + if (!children_inside_clip_) { + TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping"); return; + } SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 230b648f50e80..3bc7e394c1033 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -18,9 +18,12 @@ PictureLayer::PictureLayer(const SkPoint& offset, will_change_(will_change) {} void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "PictureLayer::Preroll"); SkPicture* sk_picture = picture(); if (auto* cache = context->raster_cache) { + TRACE_EVENT0("flutter", "PictureLayer::RasterCache (Preroll)"); + SkMatrix ctm = matrix; ctm.postTranslate(offset_.x(), offset_.y()); #ifndef SUPPORT_FRACTIONAL_TRANSLATION @@ -50,6 +53,8 @@ void PictureLayer::Paint(PaintContext& context) const { const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); RasterCacheResult result = context.raster_cache->Get(*picture(), ctm); if (result.is_valid()) { + TRACE_EVENT_INSTANT0("flutter", "raster cache hit"); + result.draw(*context.leaf_nodes_canvas); return; } diff --git a/flow/layers/texture_layer.cc b/flow/layers/texture_layer.cc index 848f69c8a115a..e5df2b795dd34 100644 --- a/flow/layers/texture_layer.cc +++ b/flow/layers/texture_layer.cc @@ -15,14 +15,19 @@ TextureLayer::TextureLayer(const SkPoint& offset, : offset_(offset), size_(size), texture_id_(texture_id), freeze_(freeze) {} void TextureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "TextureLayer::Preroll"); + set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(), size_.height())); } void TextureLayer::Paint(PaintContext& context) const { + TRACE_EVENT0("flutter", "TextureLayer::Paint"); + std::shared_ptr texture = context.texture_registry.GetTexture(texture_id_); if (!texture) { + TRACE_EVENT_INSTANT0("flutter", "null texture"); return; } texture->Paint(*context.leaf_nodes_canvas, paint_bounds(), freeze_, diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 9513e8bc0fec6..5c7bc44073236 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -25,6 +25,8 @@ TransformLayer::TransformLayer(const SkMatrix& transform) } void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "TransformLayer::Preroll"); + SkMatrix child_matrix; child_matrix.setConcat(matrix, transform_); context->mutators_stack.PushTransform(transform_); @@ -51,6 +53,7 @@ void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { #if defined(OS_FUCHSIA) void TransformLayer::UpdateScene(SceneUpdateContext& context) { + TRACE_EVENT0("flutter", "TransformLayer::UpdateScene"); FML_DCHECK(needs_system_composite()); SceneUpdateContext::Transform transform(context, transform_); From f7e4c10990edcc56fa398e9055823214b794a4b1 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 13 Jan 2020 18:09:14 -0800 Subject: [PATCH 2/4] Revert FuchsiaSystemCompistedLayer changes --- ci/licenses_golden/licenses_flutter | 4 - flow/BUILD.gn | 4 - flow/layers/child_scene_layer.cc | 17 +-- flow/layers/elevated_container_layer.cc | 49 -------- flow/layers/elevated_container_layer.h | 34 ------ .../layers/fuchsia_system_composited_layer.cc | 55 --------- flow/layers/fuchsia_system_composited_layer.h | 37 ------ flow/layers/layer.h | 5 +- flow/layers/layer_tree.h | 1 + flow/layers/opacity_layer.cc | 70 +++-------- flow/layers/opacity_layer.h | 41 ++----- flow/layers/physical_shape_layer.cc | 48 ++++---- flow/layers/physical_shape_layer.h | 41 +++---- flow/layers/physical_shape_layer_unittests.cc | 8 +- flow/scene_update_context.cc | 109 ++++++++++-------- flow/scene_update_context.h | 41 ++++--- 16 files changed, 149 insertions(+), 415 deletions(-) delete mode 100644 flow/layers/elevated_container_layer.cc delete mode 100644 flow/layers/elevated_container_layer.h delete mode 100644 flow/layers/fuchsia_system_composited_layer.cc delete mode 100644 flow/layers/fuchsia_system_composited_layer.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ca89f381bd203..b6d7374267808 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -48,10 +48,6 @@ FILE: ../../../flutter/flow/layers/color_filter_layer_unittests.cc FILE: ../../../flutter/flow/layers/container_layer.cc FILE: ../../../flutter/flow/layers/container_layer.h FILE: ../../../flutter/flow/layers/container_layer_unittests.cc -FILE: ../../../flutter/flow/layers/elevated_container_layer.cc -FILE: ../../../flutter/flow/layers/elevated_container_layer.h -FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.cc -FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.h FILE: ../../../flutter/flow/layers/image_filter_layer.cc FILE: ../../../flutter/flow/layers/image_filter_layer.h FILE: ../../../flutter/flow/layers/image_filter_layer_unittests.cc diff --git a/flow/BUILD.gn b/flow/BUILD.gn index dad0635fa760a..9fde3ec1da84c 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -28,8 +28,6 @@ source_set("flow") { "layers/color_filter_layer.h", "layers/container_layer.cc", "layers/container_layer.h", - "layers/elevated_container_layer.cc", - "layers/elevated_container_layer.h", "layers/image_filter_layer.cc", "layers/image_filter_layer.h", "layers/layer.cc", @@ -80,8 +78,6 @@ source_set("flow") { sources += [ "layers/child_scene_layer.cc", "layers/child_scene_layer.h", - "layers/fuchsia_system_composited_layer.cc", - "layers/fuchsia_system_composited_layer.h", "scene_update_context.cc", "scene_update_context.h", "view_holder.cc", diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 524878817483e..48dc92d080b6f 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -20,25 +20,10 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id, void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll"); set_needs_system_composite(true); - - // An alpha "hole punch" is required if the frame behind us is not opaque. - if (!context->is_opaque) { - set_paint_bounds( - SkRect::MakeXYWH(offset_.fX, offset_.fY, size_.fWidth, size_.fHeight)); - } } void ChildSceneLayer::Paint(PaintContext& context) const { - TRACE_EVENT0("flutter", "ChildSceneLayer::Paint"); - FML_DCHECK(needs_painting()); - - // If we are being rendered into our own frame using the system compositor, - // then it is neccesary to "punch a hole" in the canvas/frame behind us so - // that group opacity looks correct. - SkPaint paint; - paint.setColor(SK_ColorTRANSPARENT); - paint.setBlendMode(SkBlendMode::kSrc); - context.leaf_nodes_canvas->drawRect(paint_bounds(), paint); + FML_NOTREACHED() << "This layer never needs painting."; } void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) { diff --git a/flow/layers/elevated_container_layer.cc b/flow/layers/elevated_container_layer.cc deleted file mode 100644 index cd68b06713992..0000000000000 --- a/flow/layers/elevated_container_layer.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Flutter 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 "flutter/flow/layers/elevated_container_layer.h" - -namespace flutter { -namespace { - -float ClampElevation(float elevation, - float parent_elevation, - float max_elevation) { - // TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be - // able to have developers specify the behavior here to alternatives besides - // clamping, like normalization on some arbitrary curve. - float clamped_elevation = elevation; - if (max_elevation > -1 && (parent_elevation + elevation) > max_elevation) { - // Clamp the local z coordinate at our max bound. Take into account the - // parent z position here to fix clamping in cases where the child is - // overflowing because of its parents. - clamped_elevation = max_elevation - parent_elevation; - } - - return clamped_elevation; -} - -} // namespace - -ElevatedContainerLayer::ElevatedContainerLayer(float elevation) - : elevation_(elevation), clamped_elevation_(elevation) {} - -void ElevatedContainerLayer::Preroll(PrerollContext* context, - const SkMatrix& matrix) { - TRACE_EVENT0("flutter", "ElevatedContainerLayer::Preroll"); - - // Track total elevation as we walk the tree, in order to deal with bounds - // overflow in z. - parent_elevation_ = context->total_elevation; - clamped_elevation_ = ClampElevation(elevation_, parent_elevation_, - context->frame_physical_depth); - context->total_elevation += clamped_elevation_; - - ContainerLayer::Preroll(context, matrix); - - // Restore the elevation for our parent. - context->total_elevation = parent_elevation_; -} - -} // namespace flutter diff --git a/flow/layers/elevated_container_layer.h b/flow/layers/elevated_container_layer.h deleted file mode 100644 index 9c7a8b051f118..0000000000000 --- a/flow/layers/elevated_container_layer.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter 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 FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_ -#define FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_ - -#include "flutter/flow/layers/container_layer.h" - -namespace flutter { - -class ElevatedContainerLayer : public ContainerLayer { - public: - ElevatedContainerLayer(float elevation); - ~ElevatedContainerLayer() override = default; - - void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - - float elevation() const { return clamped_elevation_; } - float total_elevation() const { - return parent_elevation_ + clamped_elevation_; - } - - private: - float parent_elevation_ = 0.0f; - float elevation_ = 0.0f; - float clamped_elevation_ = 0.0f; - - FML_DISALLOW_COPY_AND_ASSIGN(ElevatedContainerLayer); -}; - -} // namespace flutter - -#endif // FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_ diff --git a/flow/layers/fuchsia_system_composited_layer.cc b/flow/layers/fuchsia_system_composited_layer.cc deleted file mode 100644 index 8c4a1b2ae26e3..0000000000000 --- a/flow/layers/fuchsia_system_composited_layer.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 The Flutter 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 "flutter/flow/layers/fuchsia_system_composited_layer.h" - -namespace flutter { - -FuchsiaSystemCompositedLayer::FuchsiaSystemCompositedLayer(SkColor color, - SkAlpha opacity, - float elevation) - : ElevatedContainerLayer(elevation), color_(color), opacity_(opacity) {} - -void FuchsiaSystemCompositedLayer::Preroll(PrerollContext* context, - const SkMatrix& matrix) { - TRACE_EVENT0("flutter", "FuchsiaSystemCompositedLayer::Preroll"); - - const float parent_is_opaque = context->is_opaque; - context->mutators_stack.PushOpacity(opacity_); - context->is_opaque = parent_is_opaque && (opacity_ == SK_AlphaOPAQUE); - ElevatedContainerLayer::Preroll(context, matrix); - context->is_opaque = parent_is_opaque; - context->mutators_stack.Pop(); -} - -void FuchsiaSystemCompositedLayer::UpdateScene(SceneUpdateContext& context) { - FML_DCHECK(needs_system_composite()); - - // Retained rendering: speedup by reusing a retained entity node if - // possible. When an entity node is reused, no paint layer is added to the - // frame so we won't call Paint. - LayerRasterCacheKey key(unique_id(), context.Matrix()); - if (context.HasRetainedNode(key)) { - TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit"); - const scenic::EntityNode& retained_node = context.GetRetainedNode(key); - FML_DCHECK(context.top_entity()); - FML_DCHECK(retained_node.session() == context.session()); - context.top_entity()->embedder_node().AddChild(retained_node); - return; - } - - TRACE_EVENT_INSTANT0("flutter", "retained cache miss, creating"); - // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame(context, rrect_, color_, opacity_ / 255.0f, - elevation(), this); - for (auto& layer : layers()) { - if (layer->needs_painting()) { - frame.AddPaintLayer(layer.get()); - } - } - - ElevatedContainerLayer::UpdateScene(context); -} - -} // namespace flutter diff --git a/flow/layers/fuchsia_system_composited_layer.h b/flow/layers/fuchsia_system_composited_layer.h deleted file mode 100644 index 2fe00ee6d550f..0000000000000 --- a/flow/layers/fuchsia_system_composited_layer.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Flutter 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 FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_ -#define FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_ - -#include "flutter/flow/layers/elevated_container_layer.h" -#include "flutter/flow/scene_update_context.h" - -namespace flutter { - -class FuchsiaSystemCompositedLayer : public ElevatedContainerLayer { - public: - static bool can_system_composite() { return true; } - - FuchsiaSystemCompositedLayer(SkColor color, SkAlpha opacity, float elevation); - - void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - void UpdateScene(SceneUpdateContext& context) override; - - void set_dimensions(SkRRect rrect) { rrect_ = rrect; } - - SkColor color() const { return color_; } - SkAlpha opacity() const { return opacity_; } - - private: - SkRRect rrect_ = SkRRect::MakeEmpty(); - SkColor color_ = SK_ColorTRANSPARENT; - SkAlpha opacity_ = SK_AlphaOPAQUE; - - FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaSystemCompositedLayer); -}; - -} // namespace flutter - -#endif // FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_ diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 63c7cdb316d7e..ca7eecd5507fc 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -61,11 +61,10 @@ struct PrerollContext { float frame_physical_depth; float frame_device_pixel_ratio; - // These allow us to track properties like elevation, opacity, and the - // prescence of a platform view during Preroll. + // These allow us to track properties like elevation and opacity which stack + // with each other during Preroll. float total_elevation = 0.0f; bool has_platform_view = false; - bool is_opaque = true; }; // Represents a single composited layer. Created on the UI thread but then diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 21ba509f09ae6..43fc58a9746b6 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -14,6 +14,7 @@ #include "flutter/fml/macros.h" #include "flutter/fml/time/time_delta.h" #include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/core/SkSize.h" namespace flutter { diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index 5892fff7792a6..32f57179a3756 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -9,29 +9,8 @@ namespace flutter { -// The OpacityLayer has no real "elevation", but we want to avoid Z-fighting -// when using the system compositor. Choose a small but non-zero value for -// this. -constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.01f; - -#if !defined(OS_FUCHSIA) -void OpacityLayerBase::Preroll(PrerollContext* context, - const SkMatrix& matrix) { - const float parent_is_opaque = context->is_opaque; - - context->mutators_stack.PushOpacity(opacity_); - context->is_opaque = parent_is_opaque && (opacity_ == SK_AlphaOPAQUE); - ContainerLayer::Preroll(context, matrix); - context->is_opaque = parent_is_opaque; - context->mutators_stack.Pop(); -} -#endif - -OpacityLayer::OpacityLayer(SkAlpha opacity, const SkPoint& offset) - : OpacityLayerBase(SK_ColorTRANSPARENT, - opacity, - kOpacityElevationWhenUsingSystemCompositor), - offset_(offset) { +OpacityLayer::OpacityLayer(int alpha, const SkPoint& offset) + : alpha_(alpha), offset_(offset) { // Ensure OpacityLayer has only one direct child. // // This is needed to ensure that retained rendering can always be applied to @@ -52,54 +31,34 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { ContainerLayer* container = GetChildContainer(); FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf. - // Factor in the offset during Preroll. |OpacityLayerBase| will handle the - // opacity. SkMatrix child_matrix = matrix; child_matrix.postTranslate(offset_.fX, offset_.fY); context->mutators_stack.PushTransform( SkMatrix::MakeTrans(offset_.fX, offset_.fY)); + context->mutators_stack.PushOpacity(alpha_); Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); - OpacityLayerBase::Preroll(context, child_matrix); + ContainerLayer::Preroll(context, child_matrix); + context->mutators_stack.Pop(); context->mutators_stack.Pop(); + set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY)); - // When using the system compositor, do not include the offset since we are - // rendering as a separate piece of geometry and the offset will be baked into - // that geometry's transform. - if (OpacityLayerBase::can_system_composite() && needs_system_composite()) { - set_dimensions(SkRRect::MakeRect(paint_bounds())); - } else { - set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY)); - - if (!context->has_platform_view && context->raster_cache && - SkRect::Intersects(context->cull_rect, paint_bounds())) { - SkMatrix ctm = child_matrix; + if (!context->has_platform_view && context->raster_cache && + SkRect::Intersects(context->cull_rect, paint_bounds())) { + SkMatrix ctm = child_matrix; #ifndef SUPPORT_FRACTIONAL_TRANSLATION - ctm = RasterCache::GetIntegralTransCTM(ctm); + ctm = RasterCache::GetIntegralTransCTM(ctm); #endif - context->raster_cache->Prepare(context, container, ctm); - } + context->raster_cache->Prepare(context, container, ctm); } } -#if defined(OS_FUCHSIA) - -void OpacityLayer::UpdateScene(SceneUpdateContext& context) { - SceneUpdateContext::Transform transform( - context, SkMatrix::MakeTrans(offset_.fX, offset_.fY)); - - // OpacityLayerBase will handle applying the opacity itself. - OpacityLayerBase::UpdateScene(context); -} - -#endif - void OpacityLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "OpacityLayer::Paint"); FML_DCHECK(needs_painting()); SkPaint paint; - paint.setAlpha(opacity()); + paint.setAlpha(alpha_); SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->translate(offset_.fX, offset_.fY); @@ -126,7 +85,8 @@ void OpacityLayer::Paint(PaintContext& context) const { // RasterCache::GetIntegralTransCTM optimization. // // Note that the following lines are only accessible when the raster cache is - // not available, or when a cache miss occurs. + // not available (e.g., when we're using the software backend in golden + // tests). SkRect saveLayerBounds; paint_bounds() .makeOffset(-offset_.fX, -offset_.fY) @@ -134,7 +94,7 @@ void OpacityLayer::Paint(PaintContext& context) const { Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint); - OpacityLayerBase::Paint(context); + PaintChildren(context); } ContainerLayer* OpacityLayer::GetChildContainer() const { diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index f4951e0557c70..92ae4cd1eadc7 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -5,42 +5,15 @@ #ifndef FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_ #define FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_ -#include "flutter/flow/layers/elevated_container_layer.h" -#if defined(OS_FUCHSIA) -#include "flutter/flow/layers/fuchsia_system_composited_layer.h" -#endif +#include "flutter/flow/layers/container_layer.h" namespace flutter { -#if !defined(OS_FUCHSIA) -class OpacityLayerBase : public ContainerLayer { - public: - static bool can_system_composite() { return false; } - - OpacityLayerBase(SkColor color, SkAlpha opacity, float elevation) - : color_(color), opacity_(opacity) {} - - void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - - void set_dimensions(SkRRect rrect) {} - - SkColor color() const { return color_; } - SkAlpha opacity() const { return opacity_; } - float elevation() const { return 0; } - - private: - SkColor color_; - SkAlpha opacity_; -}; -#else -using OpacityLayerBase = FuchsiaSystemCompositedLayer; -#endif - // Don't add an OpacityLayer with no children to the layer tree. Painting an // OpacityLayer is very costly due to the saveLayer call. If there's no child, // having the OpacityLayer or not has the same effect. In debug_unopt build, // |Preroll| will assert if there are no children. -class OpacityLayer : public OpacityLayerBase { +class OpacityLayer : public ContainerLayer { public: // An offset is provided here because OpacityLayer.addToScene method in the // Flutter framework can take an optional offset argument. @@ -52,19 +25,21 @@ class OpacityLayer : public OpacityLayerBase { // the retained rendering inefficient as a small offset change could propagate // to many leaf layers. Therefore we try to capture that offset here to stop // the propagation as repainting the OpacityLayer is expensive. - OpacityLayer(SkAlpha alpha, const SkPoint& offset); + OpacityLayer(int alpha, const SkPoint& offset); void Add(std::shared_ptr layer) override; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; -#if defined(OS_FUCHSIA) - void UpdateScene(SceneUpdateContext& context) override; -#endif + void Paint(PaintContext& context) const override; + // TODO(chinmaygarde): Once SCN-139 is addressed, introduce a new node in the + // session scene hierarchy. + private: ContainerLayer* GetChildContainer() const; + int alpha_; SkPoint offset_; FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer); diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 524c5a2ac939a..2a4b99a188ea0 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -17,12 +17,9 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, float elevation, const SkPath& path, Clip clip_behavior) -#if !defined(OS_FUCHSIA) - : PhysicalShapeLayerBase(color, elevation), -#else - : PhysicalShapeLayerBase(color, /*opacity=*/1.f, elevation), -#endif + : color_(color), shadow_color_(shadow_color), + elevation_(elevation), path_(path), isRect_(false), clip_behavior_(clip_behavior) { @@ -45,35 +42,33 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, // an SkPath. frameRRect_ = SkRRect::MakeRect(path.getBounds()); } - - set_dimensions(frameRRect_); } void PhysicalShapeLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "PhysicalShapeLayer::Preroll"); - Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); - PhysicalShapeLayerBase::Preroll(context, matrix); - if (elevation() == 0) { + context->total_elevation += elevation_; + total_elevation_ = context->total_elevation; + SkRect child_paint_bounds; + PrerollChildren(context, matrix, &child_paint_bounds); + context->total_elevation -= elevation_; + + if (elevation_ == 0) { set_paint_bounds(path_.getBounds()); } else { - if (PhysicalShapeLayerBase::can_system_composite()) { - set_needs_system_composite(true); - return; - } - //#if defined(OS_FUCHSIA) - // // Let the system compositor draw all shadows for us. - // set_needs_system_composite(true); - //#else +#if defined(OS_FUCHSIA) + // Let the system compositor draw all shadows for us. + set_needs_system_composite(true); +#else // We will draw the shadow in Paint(), so add some margin to the paint // bounds to leave space for the shadow. We fill this whole region and clip // children to it so we don't need to join the child paint bounds. - set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation(), + set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation_, context->frame_device_pixel_ratio)); - //#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) } } @@ -98,9 +93,8 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) { TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame(context, frameRRect_, color(), opacity(), - elevation(), this); - + SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_, + total_elevation_, this); for (auto& layer : layers()) { if (layer->needs_painting()) { frame.AddPaintLayer(layer.get()); @@ -116,14 +110,14 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint"); FML_DCHECK(needs_painting()); - if (elevation() != 0) { - DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation(), - SkColorGetA(color()) != 0xff, context.frame_device_pixel_ratio); + if (elevation_ != 0) { + DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_, + SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio); } // Call drawPath without clip if possible for better performance. SkPaint paint; - paint.setColor(color()); + paint.setColor(color_); paint.setAntiAlias(true); if (clip_behavior_ != Clip::antiAliasWithSaveLayer) { context.leaf_nodes_canvas->drawPath(path_, paint); diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index 34b3c59fe355b..40ff19cfac348 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -5,33 +5,18 @@ #ifndef FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_ #define FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_ -#include "flutter/flow/layers/elevated_container_layer.h" -#if defined(OS_FUCHSIA) -#include "flutter/flow/layers/fuchsia_system_composited_layer.h" -#endif +#include "flutter/flow/layers/container_layer.h" namespace flutter { -#if !defined(OS_FUCHSIA) -class PhysicalShapeLayerBase : public ElevatedContainerLayer { +class PhysicalShapeLayer : public ContainerLayer { public: - static bool can_system_composite() { return false; } - - PhysicalShapeLayerBase(SkColor color, float elevation) - : ElevatedContainerLayer(elevation), color_(color) {} - - void set_dimensions(SkRRect rrect) {} - SkColor color() const { return color_; } - - private: - SkColor color_; -}; -#else -using PhysicalShapeLayerBase = FuchsiaSystemCompositedLayer; -#endif + PhysicalShapeLayer(SkColor color, + SkColor shadow_color, + float elevation, + const SkPath& path, + Clip clip_behavior); -class PhysicalShapeLayer : public PhysicalShapeLayerBase { - public: static SkRect ComputeShadowBounds(const SkRect& bounds, float elevation, float pixel_ratio); @@ -42,13 +27,8 @@ class PhysicalShapeLayer : public PhysicalShapeLayerBase { bool transparentOccluder, SkScalar dpr); - PhysicalShapeLayer(SkColor color, - SkColor shadow_color, - float elevation, - const SkPath& path, - Clip clip_behavior); - void Preroll(PrerollContext* context, const SkMatrix& matrix) override; + void Paint(PaintContext& context) const override; bool UsesSaveLayer() const { @@ -59,8 +39,13 @@ class PhysicalShapeLayer : public PhysicalShapeLayerBase { void UpdateScene(SceneUpdateContext& context) override; #endif // defined(OS_FUCHSIA) + float total_elevation() const { return total_elevation_; } + private: + SkColor color_; SkColor shadow_color_; + float elevation_ = 0.0f; + float total_elevation_ = 0.0f; SkPath path_; bool isRect_; SkRRect frameRRect_; diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index d13116c9c44a0..a89f050999478 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -234,10 +234,10 @@ static bool ReadbackResult(PrerollContext* context, const SkMatrix initial_matrix = SkMatrix(); const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); const SkPath layer_path = SkPath().addRect(layer_bounds); - auto layer = - std::make_shared(SK_ColorGREEN, SK_ColorBLACK, - 0.0f, // elevation - layer_path, clip_behavior); + auto layer = std::make_shared(SK_ColorGREEN, + SK_ColorBLACK, 1.0f, 1.0f, + 0.0f, // elevation + layer_path, clip_behavior); if (child != nullptr) { layer->Add(child); } diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index 5ffcc4b272ce9..e6d74935f6e83 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -7,7 +7,6 @@ #include "flutter/flow/layers/layer.h" #include "flutter/flow/matrix_decomposition.h" #include "flutter/fml/trace_event.h" -#include "include/core/SkColor.h" namespace flutter { @@ -60,16 +59,18 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, scenic::ShapeNode shape_node, const SkRRect& rrect, SkColor color, - float opacity, const SkRect& paint_bounds, std::vector paint_layers, Layer* layer) { + // Frames always clip their children. + SetEntityNodeClipPlanes(entity_node, rrect.getBounds()); + // TODO(SCN-1274): SetClip() will be deleted. + entity_node.SetClip(0u, true /* clip to self */); + // We don't need a shape if the frame is zero size. if (rrect.isEmpty()) return; - SetEntityNodeClipPlanes(entity_node, rrect.getBounds()); - // isEmpty should account for this, but we are adding these experimental // checks to validate if this is the root cause for b/144933519. if (std::isnan(rrect.width()) || std::isnan(rrect.height())) { @@ -101,9 +102,7 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, // Check whether a solid color will suffice. if (paint_layers.empty()) { - scenic::Material material(session_); - SetMaterialColor(material, color, opacity); - shape_node.SetMaterial(material); + SetShapeColor(shape_node, color); return; } @@ -111,38 +110,43 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, const float scale_x = ScaleX(); const float scale_y = ScaleY(); + // Apply a texture to the whole shape. + SetShapeTextureAndColor(shape_node, color, scale_x, scale_y, shape_bounds, + std::move(paint_layers), layer, + std::move(entity_node)); +} + +void SceneUpdateContext::SetShapeTextureAndColor( + scenic::ShapeNode& shape_node, + SkColor color, + SkScalar scale_x, + SkScalar scale_y, + const SkRect& paint_bounds, + std::vector paint_layers, + Layer* layer, + scenic::EntityNode entity_node) { scenic::Image* image = GenerateImageIfNeeded( - color, scale_x, scale_y, shape_bounds, std::move(paint_layers), layer, + color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer, std::move(entity_node)); if (image != nullptr) { scenic::Material material(session_); - - // The final shape's color is material_color * texture_color. The passed in - // material color was already used as a background when generating the - // texture, so set the model color to |SK_ColorWHITE| in order to allow - // using the texture's color unmodified. - SetMaterialColor(material, SK_ColorWHITE, opacity); material.SetTexture(*image); shape_node.SetMaterial(material); return; } - // No texture was needed, so apply a solid color to the whole shape. - if (SkColorGetA(color) != 0 && opacity != 0.0f) { - scenic::Material material(session_); + SetShapeColor(shape_node, color); +} - SetMaterialColor(material, color, opacity); - shape_node.SetMaterial(material); +void SceneUpdateContext::SetShapeColor(scenic::ShapeNode& shape_node, + SkColor color) { + if (SkColorGetA(color) == 0) return; - } -} -void SceneUpdateContext::SetMaterialColor(scenic::Material& material, - SkColor color, - float opacity) { - const SkAlpha color_alpha = (SkAlpha)(SkColorGetA(color) * opacity); + scenic::Material material(session_); material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), - color_alpha); + SkColorGetA(color)); + shape_node.SetMaterial(material); } scenic::Image* SceneUpdateContext::GenerateImageIfNeeded( @@ -231,7 +235,6 @@ SceneUpdateContext::Entity::Entity(SceneUpdateContext& context) entity_node_(context.session()) { if (previous_entity_) previous_entity_->embedder_node().AddChild(entity_node_); - context.top_entity_ = this; } @@ -290,37 +293,43 @@ SceneUpdateContext::Transform::~Transform() { context().top_scale_y_ = previous_scale_y_; } -SceneUpdateContext::Clip::Clip(SceneUpdateContext& context, - const SkRect& shape_bounds) - : Entity(context) { - SetEntityNodeClipPlanes(entity_node(), shape_bounds); +SceneUpdateContext::Shape::Shape(SceneUpdateContext& context) + : Entity(context), shape_node_(context.session()) { + entity_node().AddChild(shape_node_); } SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, - float opacity, - float elevation, + float local_elevation, + float world_elevation, Layer* layer) - : Entity(context), - opacity_node_(context.session()), - shape_node_(context.session()), - layer_(layer), + : Shape(context), rrect_(rrect), - paint_bounds_(SkRect::MakeEmpty()), color_(color), - opacity_(opacity) { - entity_node().SetTranslation(0.f, 0.f, -elevation); - - entity_node().AddChild(shape_node_); - entity_node().AddChild(opacity_node_); - opacity_node_.SetOpacity(opacity_); + paint_bounds_(SkRect::MakeEmpty()), + layer_(layer) { + const float depth = context.frame_physical_depth(); + if (depth > -1 && world_elevation > depth) { + // TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be + // able to have developers specify the behavior here to alternatives besides + // clamping, like normalization on some arbitrary curve. + + // Clamp the local z coordinate at our max bound. Take into account the + // parent z position here to fix clamping in cases where the child is + // overflowing because of its parents. + const float parent_elevation = world_elevation - local_elevation; + local_elevation = depth - parent_elevation; + } + if (local_elevation != 0.0) { + entity_node().SetTranslation(0.f, 0.f, -local_elevation); + } } SceneUpdateContext::Frame::~Frame() { - context().CreateFrame(std::move(entity_node()), std::move(shape_node_), - rrect_, color_, opacity_, paint_bounds_, - std::move(paint_layers_), layer_); + context().CreateFrame(std::move(entity_node()), std::move(shape_node()), + rrect_, color_, paint_bounds_, std::move(paint_layers_), + layer_); } void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { @@ -329,4 +338,10 @@ void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { paint_bounds_.join(layer->paint_bounds()); } +SceneUpdateContext::Clip::Clip(SceneUpdateContext& context, + const SkRect& shape_bounds) + : Entity(context) { + SetEntityNodeClipPlanes(entity_node(), shape_bounds); +} + } // namespace flutter diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index c992fa20bba36..989fa83fb21bf 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -89,20 +89,25 @@ class SceneUpdateContext { float scale_x, float scale_y, float scale_z); - ~Transform() override; + virtual ~Transform(); private: float const previous_scale_x_; float const previous_scale_y_; }; - class Clip : public Entity { + class Shape : public Entity { public: - Clip(SceneUpdateContext& context, const SkRect& shape_bounds); - ~Clip() override = default; + Shape(SceneUpdateContext& context); + virtual ~Shape() = default; + + scenic::ShapeNode& shape_node() { return shape_node_; } + + private: + scenic::ShapeNode shape_node_; }; - class Frame : public Entity { + class Frame : public Shape { public: // When layer is not nullptr, the frame is associated with a layer subtree // rooted with that layer. The frame may then create a surface that will be @@ -110,25 +115,26 @@ class SceneUpdateContext { Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, - float opacity = 1.0f, - float elevation = 0.0f, + float local_elevation = 0.0f, + float parent_elevation = 0.0f, Layer* layer = nullptr); - ~Frame() override; + virtual ~Frame(); - scenic::ContainerNode& embedder_node() override { return opacity_node_; } void AddPaintLayer(Layer* layer); private: - scenic::OpacityNodeHACK opacity_node_; - scenic::ShapeNode shape_node_; + const SkRRect rrect_; + SkColor const color_; std::vector paint_layers_; + SkRect paint_bounds_; Layer* layer_; + }; - SkRRect rrect_; - SkRect paint_bounds_; - SkColor color_; - float opacity_; + class Clip : public Entity { + public: + Clip(SceneUpdateContext& context, const SkRect& shape_bounds); + ~Clip() = default; }; SceneUpdateContext(scenic::Session* session, @@ -201,7 +207,6 @@ class SceneUpdateContext { scenic::ShapeNode shape_node, const SkRRect& rrect, SkColor color, - float opacity, const SkRect& paint_bounds, std::vector paint_layers, Layer* layer); @@ -213,9 +218,7 @@ class SceneUpdateContext { std::vector paint_layers, Layer* layer, scenic::EntityNode entity_node); - void SetMaterialColor(scenic::Material& material, - SkColor color, - float opacity); + void SetShapeColor(scenic::ShapeNode& shape_node, SkColor color); scenic::Image* GenerateImageIfNeeded(SkColor color, SkScalar scale_x, SkScalar scale_y, From b740240f3cb3d4d350722f21294e99393001673b Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 13 Jan 2020 18:17:44 -0800 Subject: [PATCH 3/4] Re-add opacity w/o elevation changes --- flow/layers/child_scene_layer.cc | 18 ++- flow/layers/layer.h | 5 +- flow/layers/layer_tree.cc | 2 +- flow/layers/opacity_layer.cc | 76 ++++++++++-- flow/layers/opacity_layer.h | 11 +- flow/layers/physical_shape_layer.cc | 4 +- flow/layers/physical_shape_layer_unittests.cc | 2 +- flow/scene_update_context.cc | 111 ++++++++++-------- flow/scene_update_context.h | 41 +++---- 9 files changed, 179 insertions(+), 91 deletions(-) diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 48dc92d080b6f..4a5358053928f 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -20,10 +20,26 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id, void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll"); set_needs_system_composite(true); + + // An alpha "hole punch" is required if the frame behind us is not opaque. + if (!context->is_opaque) { + set_paint_bounds( + SkRect::MakeXYWH(offset_.fX, offset_.fY, size_.fWidth, size_.fHeight)); + } } void ChildSceneLayer::Paint(PaintContext& context) const { - FML_NOTREACHED() << "This layer never needs painting."; + TRACE_EVENT0("flutter", "ChildSceneLayer::Paint"); + FML_DCHECK(needs_painting()); + FML_DCHECK(needs_system_composite()); + + // If we are being rendered into our own frame using the system compositor, + // then it is neccesary to "punch a hole" in the canvas/frame behind us so + // that group opacity looks correct. + SkPaint paint; + paint.setColor(SK_ColorTRANSPARENT); + paint.setBlendMode(SkBlendMode::kSrc); + context.leaf_nodes_canvas->drawRect(paint_bounds(), paint); } void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) { diff --git a/flow/layers/layer.h b/flow/layers/layer.h index ca7eecd5507fc..63c7cdb316d7e 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -61,10 +61,11 @@ struct PrerollContext { float frame_physical_depth; float frame_device_pixel_ratio; - // These allow us to track properties like elevation and opacity which stack - // with each other during Preroll. + // These allow us to track properties like elevation, opacity, and the + // prescence of a platform view during Preroll. float total_elevation = 0.0f; bool has_platform_view = false; + bool is_opaque = true; }; // Represents a single composited layer. Created on the UI thread but then diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index dd9e6b4f02b01..37c28e861bf8a 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -83,7 +83,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, context, SkRRect::MakeRect( SkRect::MakeWH(frame_size_.width(), frame_size_.height())), - SK_ColorTRANSPARENT); + SK_ColorTRANSPARENT, SK_AlphaOPAQUE); if (root_layer_->needs_system_composite()) { root_layer_->UpdateScene(context); } diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index 32f57179a3756..8c804873cdfc1 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -9,7 +9,12 @@ namespace flutter { -OpacityLayer::OpacityLayer(int alpha, const SkPoint& offset) +// The OpacityLayer has no real "elevation", but we want to avoid Z-fighting +// when using the system compositor. Choose a small but non-zero value for +// this. +constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.01f; + +OpacityLayer::OpacityLayer(SkAlpha alpha, const SkPoint& offset) : alpha_(alpha), offset_(offset) { // Ensure OpacityLayer has only one direct child. // @@ -31,8 +36,13 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { ContainerLayer* container = GetChildContainer(); FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf. + const bool parent_is_opaque = context->is_opaque; SkMatrix child_matrix = matrix; child_matrix.postTranslate(offset_.fX, offset_.fY); + + total_elevation_ = context->total_elevation; + context->total_elevation += kOpacityElevationWhenUsingSystemCompositor; + context->is_opaque = parent_is_opaque && (alpha_ == SK_AlphaOPAQUE); context->mutators_stack.PushTransform( SkMatrix::MakeTrans(offset_.fX, offset_.fY)); context->mutators_stack.PushOpacity(alpha_); @@ -41,15 +51,28 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { ContainerLayer::Preroll(context, child_matrix); context->mutators_stack.Pop(); context->mutators_stack.Pop(); - set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY)); - - if (!context->has_platform_view && context->raster_cache && - SkRect::Intersects(context->cull_rect, paint_bounds())) { - SkMatrix ctm = child_matrix; + context->is_opaque = parent_is_opaque; + context->total_elevation = total_elevation_; + +#if defined(OS_FUCHSIA) + if (needs_system_composite()) { + // When using the system compositor, do not include the offset since we + // are rendering as a separate piece of geometry and the offset will be + // baked into that geometry's transform. + frameRRect_ = SkRRect::MakeRect(paint_bounds()); + set_paint_bounds(SkRect::MakeEmpty()); + } else +#endif + { + set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY)); + if (!context->has_platform_view && context->raster_cache && + SkRect::Intersects(context->cull_rect, paint_bounds())) { + SkMatrix ctm = child_matrix; #ifndef SUPPORT_FRACTIONAL_TRANSLATION - ctm = RasterCache::GetIntegralTransCTM(ctm); + ctm = RasterCache::GetIntegralTransCTM(ctm); #endif - context->raster_cache->Prepare(context, container, ctm); + context->raster_cache->Prepare(context, container, ctm); + } } } @@ -97,6 +120,43 @@ void OpacityLayer::Paint(PaintContext& context) const { PaintChildren(context); } +#if defined(OS_FUCHSIA) + +void OpacityLayer::UpdateScene(SceneUpdateContext& context) { + FML_DCHECK(needs_system_composite()); + TRACE_EVENT0("flutter", "OpacityLayer::UpdateScene"); + + ContainerLayer* container = GetChildContainer(); + FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf. + + SceneUpdateContext::Transform transform( + context, SkMatrix::MakeTrans(offset_.fX, offset_.fY)); + + // Retained rendering: speedup by reusing a retained entity node if possible. + // When an entity node is reused, no paint layer is added to the frame so we + // won't call PhysicalShapeLayer::Paint. + LayerRasterCacheKey key(unique_id(), context.Matrix()); + if (context.HasRetainedNode(key)) { + TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit"); + const scenic::EntityNode& retained_node = context.GetRetainedNode(key); + FML_DCHECK(context.top_entity()); + FML_DCHECK(retained_node.session() == context.session()); + context.top_entity()->embedder_node().AddChild(retained_node); + return; + } + + TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); + // If we can't find an existing retained surface, create one. + SceneUpdateContext::Frame frame(context, frameRRect_, SK_ColorTRANSPARENT, alpha_, + kOpacityElevationWhenUsingSystemCompositor, + total_elevation_, this); + frame.AddPaintLayer(container); + + UpdateSceneChildren(context); +} + +#endif // defined(OS_FUCHSIA) + ContainerLayer* OpacityLayer::GetChildContainer() const { FML_DCHECK(layers().size() == 1); diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index 92ae4cd1eadc7..efc5dd4f83e04 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -25,7 +25,7 @@ class OpacityLayer : public ContainerLayer { // the retained rendering inefficient as a small offset change could propagate // to many leaf layers. Therefore we try to capture that offset here to stop // the propagation as repainting the OpacityLayer is expensive. - OpacityLayer(int alpha, const SkPoint& offset); + OpacityLayer(SkAlpha alpha, const SkPoint& offset); void Add(std::shared_ptr layer) override; @@ -33,14 +33,17 @@ class OpacityLayer : public ContainerLayer { void Paint(PaintContext& context) const override; - // TODO(chinmaygarde): Once SCN-139 is addressed, introduce a new node in the - // session scene hierarchy. +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context) override; +#endif // defined(OS_FUCHSIA) private: ContainerLayer* GetChildContainer() const; - int alpha_; + SkAlpha alpha_; SkPoint offset_; + SkRRect frameRRect_; + float total_elevation_ = 0.0f; FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer); }; diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 2a4b99a188ea0..c64049222a8e7 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -93,8 +93,8 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) { TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_, - total_elevation_, this); + SceneUpdateContext::Frame frame(context, frameRRect_, color_, SK_AlphaOPAQUE, + elevation_, total_elevation_, this); for (auto& layer : layers()) { if (layer->needs_painting()) { frame.AddPaintLayer(layer.get()); diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index a89f050999478..cbee13adc5a28 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -235,7 +235,7 @@ static bool ReadbackResult(PrerollContext* context, const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); const SkPath layer_path = SkPath().addRect(layer_bounds); auto layer = std::make_shared(SK_ColorGREEN, - SK_ColorBLACK, 1.0f, 1.0f, + SK_ColorBLACK, 0.0f, // elevation layer_path, clip_behavior); if (child != nullptr) { diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index e6d74935f6e83..eec5925e41ad6 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -7,6 +7,7 @@ #include "flutter/flow/layers/layer.h" #include "flutter/flow/matrix_decomposition.h" #include "flutter/fml/trace_event.h" +#include "include/core/SkColor.h" namespace flutter { @@ -56,32 +57,21 @@ SceneUpdateContext::SceneUpdateContext(scenic::Session* session, } void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, - scenic::ShapeNode shape_node, const SkRRect& rrect, SkColor color, + SkAlpha opacity, const SkRect& paint_bounds, std::vector paint_layers, Layer* layer) { - // Frames always clip their children. - SetEntityNodeClipPlanes(entity_node, rrect.getBounds()); - // TODO(SCN-1274): SetClip() will be deleted. - entity_node.SetClip(0u, true /* clip to self */); + FML_DCHECK(!rrect.isEmpty()); - // We don't need a shape if the frame is zero size. - if (rrect.isEmpty()) - return; - - // isEmpty should account for this, but we are adding these experimental - // checks to validate if this is the root cause for b/144933519. - if (std::isnan(rrect.width()) || std::isnan(rrect.height())) { - FML_LOG(ERROR) << "Invalid RoundedRectangle"; - return; - } + // Frames always clip their children. + SkRect shape_bounds = rrect.getBounds(); + SetEntityNodeClipPlanes(entity_node, shape_bounds); - // Add a part which represents the frame's geometry for clipping purposes // and possibly for its texture. // TODO(SCN-137): Need to be able to express the radii as vectors. - SkRect shape_bounds = rrect.getBounds(); + scenic::ShapeNode shape_node(session()); scenic::RoundedRectangle shape( session_, // session rrect.width(), // width @@ -96,29 +86,35 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, shape_bounds.height() * 0.5f + shape_bounds.top(), 0.f); + // Check whether the painted layers will be visible. if (paint_bounds.isEmpty() || !paint_bounds.intersects(shape_bounds)) paint_layers.clear(); + scenic::Material material(session()); + shape_node.SetMaterial(material); + entity_node.AddChild(shape_node); + // Check whether a solid color will suffice. if (paint_layers.empty()) { - SetShapeColor(shape_node, color); - return; + SetMaterialColor(material, color, opacity); + } else { + // Apply current metrics and transformation scale factors. + const float scale_x = ScaleX(); + const float scale_y = ScaleY(); + + // Apply a texture to the whole shape. + SetMaterialTextureAndColor(material, color, opacity, scale_x, + scale_y, shape_bounds, + std::move(paint_layers), layer, + std::move(entity_node)); } - - // Apply current metrics and transformation scale factors. - const float scale_x = ScaleX(); - const float scale_y = ScaleY(); - - // Apply a texture to the whole shape. - SetShapeTextureAndColor(shape_node, color, scale_x, scale_y, shape_bounds, - std::move(paint_layers), layer, - std::move(entity_node)); } -void SceneUpdateContext::SetShapeTextureAndColor( - scenic::ShapeNode& shape_node, +void SceneUpdateContext::SetMaterialTextureAndColor( + scenic::Material& material, SkColor color, + SkAlpha opacity, SkScalar scale_x, SkScalar scale_y, const SkRect& paint_bounds, @@ -128,25 +124,28 @@ void SceneUpdateContext::SetShapeTextureAndColor( scenic::Image* image = GenerateImageIfNeeded( color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer, std::move(entity_node)); + if (image != nullptr) { - scenic::Material material(session_); + // The final shape's color is material_color * texture_color. The passed in + // material color was already used as a background when generating the + // texture, so set the model color to |SK_ColorWHITE| in order to allow + // using the texture's color unmodified. + SetMaterialColor(material, SK_ColorWHITE, opacity); material.SetTexture(*image); - shape_node.SetMaterial(material); - return; + } else { + // No texture was needed, so apply a solid color to the whole shape. + SetMaterialColor(material, color, opacity); } - SetShapeColor(shape_node, color); } -void SceneUpdateContext::SetShapeColor(scenic::ShapeNode& shape_node, - SkColor color) { - if (SkColorGetA(color) == 0) - return; - scenic::Material material(session_); +void SceneUpdateContext::SetMaterialColor(scenic::Material& material, + SkColor color, + SkAlpha opacity) { + const SkAlpha color_alpha = static_cast(((float) SkColorGetA(color) * (float) opacity) / 255.0f); material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), - SkColorGetA(color)); - shape_node.SetMaterial(material); + color_alpha); } scenic::Image* SceneUpdateContext::GenerateImageIfNeeded( @@ -293,20 +292,18 @@ SceneUpdateContext::Transform::~Transform() { context().top_scale_y_ = previous_scale_y_; } -SceneUpdateContext::Shape::Shape(SceneUpdateContext& context) - : Entity(context), shape_node_(context.session()) { - entity_node().AddChild(shape_node_); -} - SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, + SkAlpha opacity, float local_elevation, float world_elevation, Layer* layer) - : Shape(context), + : Entity(context), rrect_(rrect), color_(color), + opacity_(opacity), + opacity_node_(context.session()), paint_bounds_(SkRect::MakeEmpty()), layer_(layer) { const float depth = context.frame_physical_depth(); @@ -324,12 +321,26 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, if (local_elevation != 0.0) { entity_node().SetTranslation(0.f, 0.f, -local_elevation); } + entity_node().AddChild(opacity_node_); + opacity_node_.SetOpacity(opacity_ / 255.0f); } SceneUpdateContext::Frame::~Frame() { - context().CreateFrame(std::move(entity_node()), std::move(shape_node()), - rrect_, color_, paint_bounds_, std::move(paint_layers_), - layer_); + // We don't need a shape if the frame is zero size. + if (rrect_.isEmpty()) + return; + + // isEmpty should account for this, but we are adding these experimental + // checks to validate if this is the root cause for b/144933519. + if (std::isnan(rrect_.width()) || std::isnan(rrect_.height())) { + FML_LOG(ERROR) << "Invalid RoundedRectangle"; + return; + } + + // Add a part which represents the frame's geometry for clipping purposes + context().CreateFrame(std::move(entity_node()), + rrect_, color_, opacity_, paint_bounds_, + std::move(paint_layers_), layer_); } void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index 989fa83fb21bf..31bcb1bd57253 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -96,18 +96,7 @@ class SceneUpdateContext { float const previous_scale_y_; }; - class Shape : public Entity { - public: - Shape(SceneUpdateContext& context); - virtual ~Shape() = default; - - scenic::ShapeNode& shape_node() { return shape_node_; } - - private: - scenic::ShapeNode shape_node_; - }; - - class Frame : public Shape { + class Frame : public Entity { public: // When layer is not nullptr, the frame is associated with a layer subtree // rooted with that layer. The frame may then create a surface that will be @@ -115,17 +104,22 @@ class SceneUpdateContext { Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, + SkAlpha opacity, float local_elevation = 0.0f, float parent_elevation = 0.0f, Layer* layer = nullptr); virtual ~Frame(); + scenic::ContainerNode& embedder_node() override { return opacity_node_; } + void AddPaintLayer(Layer* layer); private: const SkRRect rrect_; SkColor const color_; + SkAlpha const opacity_; + scenic::OpacityNodeHACK opacity_node_; std::vector paint_layers_; SkRect paint_bounds_; Layer* layer_; @@ -204,21 +198,24 @@ class SceneUpdateContext { // surface (and thus the entity_node) will be retained for that layer to // improve the performance. void CreateFrame(scenic::EntityNode entity_node, - scenic::ShapeNode shape_node, const SkRRect& rrect, SkColor color, + SkAlpha opacity, const SkRect& paint_bounds, std::vector paint_layers, Layer* layer); - void SetShapeTextureAndColor(scenic::ShapeNode& shape_node, - SkColor color, - SkScalar scale_x, - SkScalar scale_y, - const SkRect& paint_bounds, - std::vector paint_layers, - Layer* layer, - scenic::EntityNode entity_node); - void SetShapeColor(scenic::ShapeNode& shape_node, SkColor color); + void SetMaterialTextureAndColor(scenic::Material& material, + SkColor color, + SkAlpha opacity, + SkScalar scale_x, + SkScalar scale_y, + const SkRect& paint_bounds, + std::vector paint_layers, + Layer* layer, + scenic::EntityNode entity_node); + void SetMaterialColor(scenic::Material& material, + SkColor color, + SkAlpha opacity); scenic::Image* GenerateImageIfNeeded(SkColor color, SkScalar scale_x, SkScalar scale_y, From a6040f247de3c67758a642ff00779a35eb8a9663 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Tue, 14 Jan 2020 18:20:58 -0800 Subject: [PATCH 4/4] Fix formatting --- flow/layers/opacity_layer.cc | 6 +++--- flow/layers/physical_shape_layer_unittests.cc | 8 ++++---- flow/scene_update_context.cc | 16 ++++++---------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index 8c804873cdfc1..e6ca90a66a42f 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -147,9 +147,9 @@ void OpacityLayer::UpdateScene(SceneUpdateContext& context) { TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame(context, frameRRect_, SK_ColorTRANSPARENT, alpha_, - kOpacityElevationWhenUsingSystemCompositor, - total_elevation_, this); + SceneUpdateContext::Frame frame( + context, frameRRect_, SK_ColorTRANSPARENT, alpha_, + kOpacityElevationWhenUsingSystemCompositor, total_elevation_, this); frame.AddPaintLayer(container); UpdateSceneChildren(context); diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index cbee13adc5a28..d13116c9c44a0 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -234,10 +234,10 @@ static bool ReadbackResult(PrerollContext* context, const SkMatrix initial_matrix = SkMatrix(); const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); const SkPath layer_path = SkPath().addRect(layer_bounds); - auto layer = std::make_shared(SK_ColorGREEN, - SK_ColorBLACK, - 0.0f, // elevation - layer_path, clip_behavior); + auto layer = + std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 0.0f, // elevation + layer_path, clip_behavior); if (child != nullptr) { layer->Add(child); } diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index eec5925e41ad6..59524bc9c6e56 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -86,7 +86,6 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, shape_bounds.height() * 0.5f + shape_bounds.top(), 0.f); - // Check whether the painted layers will be visible. if (paint_bounds.isEmpty() || !paint_bounds.intersects(shape_bounds)) paint_layers.clear(); @@ -104,9 +103,8 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, const float scale_y = ScaleY(); // Apply a texture to the whole shape. - SetMaterialTextureAndColor(material, color, opacity, scale_x, - scale_y, shape_bounds, - std::move(paint_layers), layer, + SetMaterialTextureAndColor(material, color, opacity, scale_x, scale_y, + shape_bounds, std::move(paint_layers), layer, std::move(entity_node)); } } @@ -136,14 +134,13 @@ void SceneUpdateContext::SetMaterialTextureAndColor( // No texture was needed, so apply a solid color to the whole shape. SetMaterialColor(material, color, opacity); } - } - void SceneUpdateContext::SetMaterialColor(scenic::Material& material, SkColor color, SkAlpha opacity) { - const SkAlpha color_alpha = static_cast(((float) SkColorGetA(color) * (float) opacity) / 255.0f); + const SkAlpha color_alpha = static_cast( + ((float)SkColorGetA(color) * (float)opacity) / 255.0f); material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), color_alpha); } @@ -338,9 +335,8 @@ SceneUpdateContext::Frame::~Frame() { } // Add a part which represents the frame's geometry for clipping purposes - context().CreateFrame(std::move(entity_node()), - rrect_, color_, opacity_, paint_bounds_, - std::move(paint_layers_), layer_); + context().CreateFrame(std::move(entity_node()), rrect_, color_, opacity_, + paint_bounds_, std::move(paint_layers_), layer_); } void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {