From 5df695efdff1f5b4621ae8622fb9d91dabab75b2 Mon Sep 17 00:00:00 2001 From: Michael Klimushyn Date: Wed, 17 Apr 2019 09:56:46 -0700 Subject: [PATCH] Pipe Z bounds from ViewportMetrics to Flow (flutter/engine#8583) This is the first step in making Flutter aware of and responsive to Z bound overflow. On its own this patch shouldn't result in any changes in behavior. This will need to be followed up with a patch in Fuchsia's Flutter runner to set the Z bounds after this lands, and another patch in the engine actually implementing the desired overflow behavior. This Z bound info is routed through the engine itself to make sure the bounds in flow are truly consistent from the Fuchsia runner. However these values should eventually be exposed to the framework as well. --- engine/src/flutter/flow/layers/layer.h | 1 + engine/src/flutter/flow/layers/layer_tree.cc | 2 +- .../flow/layers/physical_shape_layer.cc | 4 ++- .../flow/layers/physical_shape_layer.h | 11 +++++-- .../src/flutter/flow/scene_update_context.cc | 15 ++++++++-- .../src/flutter/flow/scene_update_context.h | 4 ++- .../lib/ui/compositing/scene_builder.cc | 2 ++ .../flutter/lib/ui/window/viewport_metrics.cc | 29 +++++++++++++++++++ .../flutter/lib/ui/window/viewport_metrics.h | 26 +++++++++++++++++ engine/src/flutter/shell/common/engine.cc | 3 +- 10 files changed, 88 insertions(+), 9 deletions(-) diff --git a/engine/src/flutter/flow/layers/layer.h b/engine/src/flutter/flow/layers/layer.h index 8cb9b6710c..dc1242f0f7 100644 --- a/engine/src/flutter/flow/layers/layer.h +++ b/engine/src/flutter/flow/layers/layer.h @@ -56,6 +56,7 @@ struct PrerollContext { const Stopwatch& engine_time; TextureRegistry& texture_registry; const bool checkerboard_offscreen_layers; + float total_elevation = 0.0f; }; // Represents a single composited layer. Created on the UI thread but then diff --git a/engine/src/flutter/flow/layers/layer_tree.cc b/engine/src/flutter/flow/layers/layer_tree.cc index 08a1990da1..0b24b52fd8 100644 --- a/engine/src/flutter/flow/layers/layer_tree.cc +++ b/engine/src/flutter/flow/layers/layer_tree.cc @@ -54,7 +54,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, context, SkRRect::MakeRect( SkRect::MakeWH(frame_size_.width(), frame_size_.height())), - SK_ColorTRANSPARENT, 0.f); + SK_ColorTRANSPARENT); if (root_layer_->needs_system_composite()) { root_layer_->UpdateScene(context); } diff --git a/engine/src/flutter/flow/layers/physical_shape_layer.cc b/engine/src/flutter/flow/layers/physical_shape_layer.cc index 93bd2664a9..5f573ad0d3 100644 --- a/engine/src/flutter/flow/layers/physical_shape_layer.cc +++ b/engine/src/flutter/flow/layers/physical_shape_layer.cc @@ -43,6 +43,8 @@ void PhysicalShapeLayer::set_path(const SkPath& path) { void PhysicalShapeLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + context->total_elevation += elevation_; + total_elevation_ = context->total_elevation; SkRect child_paint_bounds; PrerollChildren(context, matrix, &child_paint_bounds); @@ -118,7 +120,7 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) { // If we can't find an existing retained surface, create one. SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_, - this); + total_elevation_, viewport_depth_, this); for (auto& layer : layers()) { if (layer->needs_painting()) { frame.AddPaintLayer(layer.get()); diff --git a/engine/src/flutter/flow/layers/physical_shape_layer.h b/engine/src/flutter/flow/layers/physical_shape_layer.h index 45ba68e86d..46885c902b 100644 --- a/engine/src/flutter/flow/layers/physical_shape_layer.h +++ b/engine/src/flutter/flow/layers/physical_shape_layer.h @@ -16,10 +16,15 @@ class PhysicalShapeLayer : public ContainerLayer { void set_path(const SkPath& path); - void set_elevation(float elevation) { elevation_ = elevation; } void set_color(SkColor color) { color_ = color; } void set_shadow_color(SkColor shadow_color) { shadow_color_ = shadow_color; } void set_device_pixel_ratio(SkScalar dpr) { device_pixel_ratio_ = dpr; } + void set_viewport_depth(float depth) { viewport_depth_ = depth; } + + // Sets the elevation. This needs to be set before preroll because it's then + // cached by any children of this layer. Setting it after preroll will break + // their elevation calculations. + void set_elevation(float elevation) { elevation_ = elevation; } static void DrawShadow(SkCanvas* canvas, const SkPath& path, @@ -37,7 +42,9 @@ class PhysicalShapeLayer : public ContainerLayer { #endif // defined(OS_FUCHSIA) private: - float elevation_; + float elevation_ = 0.0f; + float total_elevation_ = 0.0f; + float viewport_depth_; SkColor color_; SkColor shadow_color_; SkScalar device_pixel_ratio_; diff --git a/engine/src/flutter/flow/scene_update_context.cc b/engine/src/flutter/flow/scene_update_context.cc index 07ff4d876a..3c2834a8ff 100644 --- a/engine/src/flutter/flow/scene_update_context.cc +++ b/engine/src/flutter/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 "flutter/lib/ui/window/viewport_metrics.h" namespace flow { @@ -285,15 +286,23 @@ SceneUpdateContext::Transform::~Transform() { SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, - float elevation, + float local_elevation, + float world_elevation, + float depth, Layer* layer) : Entity(context), rrect_(rrect), color_(color), paint_bounds_(SkRect::MakeEmpty()), layer_(layer) { - if (elevation != 0.0) - entity_node().SetTranslation(0.f, 0.f, -elevation); + if (local_elevation != 0.0) { + if (depth > flutter::kUnsetDepth && world_elevation >= depth) { + // TODO(mklim): Deal with bounds overflow correctly. + FML_LOG(ERROR) << "Elevation " << world_elevation << " is outside of " + << depth; + } + entity_node().SetTranslation(0.f, 0.f, -local_elevation); + } } SceneUpdateContext::Frame::~Frame() { diff --git a/engine/src/flutter/flow/scene_update_context.h b/engine/src/flutter/flow/scene_update_context.h index f19c5b8f76..925fc94935 100644 --- a/engine/src/flutter/flow/scene_update_context.h +++ b/engine/src/flutter/flow/scene_update_context.h @@ -112,7 +112,9 @@ class SceneUpdateContext { Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, - float elevation, + float local_elevation = 0.0f, + float parent_elevation = 0.0f, + float depth = 0.0f, Layer* layer = nullptr); ~Frame(); diff --git a/engine/src/flutter/lib/ui/compositing/scene_builder.cc b/engine/src/flutter/lib/ui/compositing/scene_builder.cc index e504529559..447119594f 100644 --- a/engine/src/flutter/lib/ui/compositing/scene_builder.cc +++ b/engine/src/flutter/lib/ui/compositing/scene_builder.cc @@ -190,6 +190,8 @@ fml::RefPtr SceneBuilder::pushPhysicalShape(const CanvasPath* path, layer->set_shadow_color(static_cast(shadow_color)); layer->set_device_pixel_ratio( UIDartState::Current()->window()->viewport_metrics().device_pixel_ratio); + layer->set_viewport_depth( + UIDartState::Current()->window()->viewport_metrics().physical_depth); PushLayer(layer); return EngineLayer::MakeRetained(layer); } diff --git a/engine/src/flutter/lib/ui/window/viewport_metrics.cc b/engine/src/flutter/lib/ui/window/viewport_metrics.cc index 88a9eb8434..3dabeeb1ed 100644 --- a/engine/src/flutter/lib/ui/window/viewport_metrics.cc +++ b/engine/src/flutter/lib/ui/window/viewport_metrics.cc @@ -30,6 +30,35 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio, physical_view_inset_bottom(p_physical_view_inset_bottom), physical_view_inset_left(p_physical_view_inset_left) {} +ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio, + double p_physical_width, + double p_physical_height, + double p_physical_depth, + double p_physical_padding_top, + double p_physical_padding_right, + double p_physical_padding_bottom, + double p_physical_padding_left, + double p_physical_view_inset_front, + double p_physical_view_inset_back, + double p_physical_view_inset_top, + double p_physical_view_inset_right, + double p_physical_view_inset_bottom, + double p_physical_view_inset_left) + : device_pixel_ratio(p_device_pixel_ratio), + physical_width(p_physical_width), + physical_height(p_physical_height), + physical_depth(p_physical_depth), + physical_padding_top(p_physical_padding_top), + physical_padding_right(p_physical_padding_right), + physical_padding_bottom(p_physical_padding_bottom), + physical_padding_left(p_physical_padding_left), + physical_view_inset_top(p_physical_view_inset_top), + physical_view_inset_right(p_physical_view_inset_right), + physical_view_inset_bottom(p_physical_view_inset_bottom), + physical_view_inset_left(p_physical_view_inset_left), + physical_view_inset_front(p_physical_view_inset_front), + physical_view_inset_back(p_physical_view_inset_back) {} + ViewportMetrics::ViewportMetrics(const ViewportMetrics& other) = default; } // namespace flutter diff --git a/engine/src/flutter/lib/ui/window/viewport_metrics.h b/engine/src/flutter/lib/ui/window/viewport_metrics.h index 3a40505ba3..aa0d7dc8ea 100644 --- a/engine/src/flutter/lib/ui/window/viewport_metrics.h +++ b/engine/src/flutter/lib/ui/window/viewport_metrics.h @@ -9,9 +9,12 @@ namespace flutter { +static const double kUnsetDepth = -1; + struct ViewportMetrics { ViewportMetrics(); + // Create a 2D ViewportMetrics instance. ViewportMetrics(double p_device_pixel_ratio, double p_physical_width, double p_physical_height, @@ -24,11 +27,28 @@ struct ViewportMetrics { double p_physical_view_inset_bottom, double p_physical_view_inset_left); + // Create a ViewportMetrics instance that contains z information. + ViewportMetrics(double p_device_pixel_ratio, + double p_physical_width, + double p_physical_height, + double p_physical_depth, + double p_physical_padding_top, + double p_physical_padding_right, + double p_physical_padding_bottom, + double p_physical_padding_left, + double p_physical_view_inset_front, + double p_physical_view_inset_back, + double p_physical_view_inset_top, + double p_physical_view_inset_right, + double p_physical_view_inset_bottom, + double p_physical_view_inset_left); + ViewportMetrics(const ViewportMetrics& other); double device_pixel_ratio = 1.0; double physical_width = 0; double physical_height = 0; + double physical_depth = kUnsetDepth; double physical_padding_top = 0; double physical_padding_right = 0; double physical_padding_bottom = 0; @@ -37,11 +57,14 @@ struct ViewportMetrics { double physical_view_inset_right = 0; double physical_view_inset_bottom = 0; double physical_view_inset_left = 0; + double physical_view_inset_front = kUnsetDepth; + double physical_view_inset_back = kUnsetDepth; }; struct LogicalSize { double width = 0.0; double height = 0.0; + double depth = kUnsetDepth; }; struct LogicalInset { @@ -49,11 +72,14 @@ struct LogicalInset { double top = 0.0; double right = 0.0; double bottom = 0.0; + double front = kUnsetDepth; + double back = kUnsetDepth; }; struct LogicalMetrics { LogicalSize size; double scale = 1.0; + double scale_z = 1.0; LogicalInset padding; LogicalInset view_inset; }; diff --git a/engine/src/flutter/shell/common/engine.cc b/engine/src/flutter/shell/common/engine.cc index 4d7da77e85..fdbd6bf7a8 100644 --- a/engine/src/flutter/shell/common/engine.cc +++ b/engine/src/flutter/shell/common/engine.cc @@ -237,7 +237,8 @@ void Engine::OnOutputSurfaceDestroyed() { void Engine::SetViewportMetrics(const ViewportMetrics& metrics) { bool dimensions_changed = viewport_metrics_.physical_height != metrics.physical_height || - viewport_metrics_.physical_width != metrics.physical_width; + viewport_metrics_.physical_width != metrics.physical_width || + viewport_metrics_.physical_depth != metrics.physical_depth; viewport_metrics_ = metrics; runtime_controller_->SetViewportMetrics(viewport_metrics_); if (animator_) {