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_) {