From 094b39fdc1d44009f873cdd84af1fbb7bc1fd303 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Thu, 3 Oct 2019 13:05:51 -0700 Subject: [PATCH 01/11] Remove erroneous Childview opacity --- flow/view_holder.cc | 20 +++++--------------- flow/view_holder.h | 4 ---- lib/ui/compositing.dart | 11 ----------- lib/ui/compositing/scene_host.cc | 16 +++------------- lib/ui/compositing/scene_host.h | 10 ++++------ lib/web_ui/lib/src/ui/compositing.dart | 12 ------------ 6 files changed, 12 insertions(+), 61 deletions(-) diff --git a/flow/view_holder.cc b/flow/view_holder.cc index 688f56d0987a7..51d2456c7044e 100644 --- a/flow/view_holder.cc +++ b/flow/view_holder.cc @@ -104,14 +104,11 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context, const SkSize& size, bool hit_testable) { if (pending_view_holder_token_.value) { - opacity_node_ = - std::make_unique(context.session()); entity_node_ = std::make_unique(context.session()); view_holder_ = std::make_unique( context.session(), std::move(pending_view_holder_token_), "Flutter SceneHost"); - opacity_node_->AddChild(*entity_node_); entity_node_->Attach(*view_holder_); ui_task_runner_->PostTask( [bind_callback = std::move(pending_bind_callback_), @@ -119,20 +116,18 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context, bind_callback(view_holder_id); }); } - FML_DCHECK(opacity_node_); + FML_DCHECK(entity_node_); FML_DCHECK(view_holder_); - context.top_entity()->entity_node().AddChild(*opacity_node_); + context.top_entity()->embedder_node().AddChild(*entity_node_); entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f); entity_node_->SetHitTestBehavior( hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault : fuchsia::ui::gfx::HitTestBehavior::kSuppress); - if (has_pending_opacity_) { - opacity_node_->SetOpacity(pending_opacity_); - - has_pending_opacity_ = false; - } if (has_pending_properties_) { + // TODO(dworsham): This should be derived from size and elevation. We + // should be able to Z-limit the view's box but otherwise it uses all of the + // available airspace. view_holder_->SetViewProperties(std::move(pending_properties_)); has_pending_properties_ = false; @@ -151,9 +146,4 @@ void ViewHolder::SetProperties(double width, has_pending_properties_ = true; } -void ViewHolder::SetOpacity(double opacity) { - pending_opacity_ = std::clamp(opacity, 0.0, 1.0); - has_pending_opacity_ = true; -} - } // namespace flutter diff --git a/flow/view_holder.h b/flow/view_holder.h index 9466f644aee23..174340638dcea 100644 --- a/flow/view_holder.h +++ b/flow/view_holder.h @@ -51,7 +51,6 @@ class ViewHolder { double insetBottom, double insetLeft, bool focusable); - void SetOpacity(double opacity); // Creates or updates the contained ViewHolder resource using the specified // |SceneUpdateContext|. @@ -63,7 +62,6 @@ class ViewHolder { private: fml::RefPtr ui_task_runner_; - std::unique_ptr opacity_node_; std::unique_ptr entity_node_; std::unique_ptr view_holder_; @@ -71,9 +69,7 @@ class ViewHolder { BindCallback pending_bind_callback_; fuchsia::ui::gfx::ViewProperties pending_properties_; - double pending_opacity_; bool has_pending_properties_ = false; - bool has_pending_opacity_ = false; FML_DISALLOW_COPY_AND_ASSIGN(ViewHolder); }; diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 232514c0f1805..944f2e933bf2f 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -694,13 +694,6 @@ class SceneHost extends NativeFieldWrapperClass2 { void Function(bool) viewStateChangedCallback) { _constructor(viewHolderToken, viewConnectedCallback, viewDisconnectedCallback, viewStateChangedCallback); } - SceneHost.fromViewHolderToken( - dynamic viewHolderToken, - void Function() viewConnectedCallback, - void Function() viewDisconnectedCallback, - void Function(bool) viewStateChangedCallback) { - _constructor(viewHolderToken, viewConnectedCallback, viewDisconnectedCallback, viewStateChangedCallback); - } void _constructor(dynamic viewHolderToken, void Function() viewConnectedCallback, void Function() viewDisconnectedCallback, void Function(bool) viewStateChangedCallback) native 'SceneHost_constructor'; @@ -720,8 +713,4 @@ class SceneHost extends NativeFieldWrapperClass2 { double insetBottom, double insetLeft, bool focusable) native 'SceneHost_setProperties'; - - /// Set the opacity of the linked scene. This opacity value is applied only - /// once, when the child scene is composited into our own. - void setOpacity(double opacity) native 'SceneHost_setOpacity'; } diff --git a/lib/ui/compositing/scene_host.cc b/lib/ui/compositing/scene_host.cc index 889f5cb174351..e4f83cc3ff0e8 100644 --- a/lib/ui/compositing/scene_host.cc +++ b/lib/ui/compositing/scene_host.cc @@ -85,10 +85,9 @@ namespace flutter { IMPLEMENT_WRAPPERTYPEINFO(ui, SceneHost); -#define FOR_EACH_BINDING(V) \ - V(SceneHost, dispose) \ - V(SceneHost, setProperties) \ - V(SceneHost, setOpacity) +#define FOR_EACH_BINDING(V) \ + V(SceneHost, dispose) \ + V(SceneHost, setProperties) FOR_EACH_BINDING(DART_NATIVE_CALLBACK) @@ -205,13 +204,4 @@ void SceneHost::setProperties(double width, }); } -void SceneHost::setOpacity(double opacity) { - gpu_task_runner_->PostTask([id = koid_, opacity]() { - auto* view_holder = flutter::ViewHolder::FromId(id); - FML_DCHECK(view_holder); - - view_holder->SetOpacity(opacity); - }); -} - } // namespace flutter diff --git a/lib/ui/compositing/scene_host.h b/lib/ui/compositing/scene_host.h index 9e47cf49a3645..8d45683859b9d 100644 --- a/lib/ui/compositing/scene_host.h +++ b/lib/ui/compositing/scene_host.h @@ -20,8 +20,6 @@ namespace flutter { class SceneHost : public RefCountedDartWrappable { DEFINE_WRAPPERTYPEINFO(); - FML_FRIEND_MAKE_REF_COUNTED(SceneHost); - public: static void RegisterNatives(tonic::DartLibraryNatives* natives); static fml::RefPtr Create( @@ -34,13 +32,14 @@ class SceneHost : public RefCountedDartWrappable { static void OnViewStateChanged(scenic::ResourceId id, bool state); SceneHost(fml::RefPtr viewHolderToken, - Dart_Handle viewConnectedCallback, - Dart_Handle viewDisconnectedCallback, - Dart_Handle viewStateChangedCallback); + Dart_Handle viewConnectedCallback, + Dart_Handle viewDisconnectedCallback, + Dart_Handle viewStateChangedCallback); ~SceneHost() override; zx_koid_t id() const { return koid_; } + // These are visible to Dart. void dispose(); void setProperties(double width, double height, @@ -49,7 +48,6 @@ class SceneHost : public RefCountedDartWrappable { double insetBottom, double insetLeft, bool focusable); - void setOpacity(double opacity); private: fml::RefPtr gpu_task_runner_; diff --git a/lib/web_ui/lib/src/ui/compositing.dart b/lib/web_ui/lib/src/ui/compositing.dart index d33ccc6c216a9..96d83d52fd906 100644 --- a/lib/web_ui/lib/src/ui/compositing.dart +++ b/lib/web_ui/lib/src/ui/compositing.dart @@ -383,12 +383,6 @@ class SceneHost { void Function() viewDisconnectedCallback, void Function(bool) viewStateChangedCallback); - SceneHost.fromViewHolderToken( - dynamic viewHolderToken, - void Function() viewConnectedCallback, - void Function() viewDisconnectedCallback, - void Function(bool) viewStateChangedCallback); - /// Releases the resources associated with the SceneHost. /// /// After calling this function, the SceneHost cannot be used further. @@ -400,10 +394,4 @@ class SceneHost { double insetRight, double insetBottom, double insetLeft, bool focusable) { throw UnimplementedError(); } - - /// Set the opacity of the linked scene. This opacity value is applied only - /// once, when the child scene is composited into our own. - void setOpacity(double opacity) { - throw UnimplementedError(); - } } From 9ba8b5907767e17cfce7ef2fb06f8790f33d94d1 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 11 Nov 2019 10:39:50 -0800 Subject: [PATCH 02/11] Wire frame metrics through contexts --- flow/layers/layer.h | 13 +++- flow/layers/layer_tree.cc | 62 ++++++++++++------- flow/layers/layer_tree.h | 23 +++---- flow/layers/physical_shape_layer.cc | 16 +++-- flow/layers/physical_shape_layer.h | 4 -- flow/layers/physical_shape_layer_unittests.cc | 4 +- flow/raster_cache.cc | 4 +- flow/scene_update_context.cc | 6 +- flow/scene_update_context.h | 16 ++++- lib/ui/compositing/scene.cc | 26 +++++--- lib/ui/compositing/scene.h | 2 +- lib/ui/compositing/scene_builder.cc | 8 --- lib/ui/window/viewport_metrics.cc | 16 +++-- lib/ui/window/viewport_metrics.h | 5 +- shell/common/engine.cc | 9 ++- shell/common/persistent_cache_unittests.cc | 2 +- shell/common/shell_test.cc | 20 ++++-- shell/common/shell_test.h | 8 +-- shell/common/shell_unittests.cc | 17 +++++ .../embedder/tests/embedder_unittests.cc | 1 - 20 files changed, 168 insertions(+), 94 deletions(-) diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 66944376e8ce8..ba91353140889 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -52,11 +52,18 @@ struct PrerollContext { SkColorSpace* dst_color_space; SkRect cull_rect; - // The following allows us to paint in the end of subtree preroll + // These allow us to paint in the end of subtree Preroll. const Stopwatch& raster_time; const Stopwatch& ui_time; TextureRegistry& texture_registry; const bool checkerboard_offscreen_layers; + + // These allow us to make use of the scene metrics during Preroll. + 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. float total_elevation = 0.0f; bool has_platform_view = false; }; @@ -90,6 +97,10 @@ class Layer { TextureRegistry& texture_registry; const RasterCache* raster_cache; const bool checkerboard_offscreen_layers; + + // These allow us to make use of the scene metrics during Paint. + float frame_physical_depth; + float frame_device_pixel_ratio; }; // Calls SkCanvas::saveLayer and restores the layer upon destruction. Also diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index b031ebf8cb8bd..a86d184a04533 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -11,14 +11,16 @@ namespace flutter { -LayerTree::LayerTree() - : frame_size_{}, +LayerTree::LayerTree(const SkISize& frame_size, + float frame_physical_depth, + float frame_device_pixel_ratio) + : frame_size_(frame_size), + frame_physical_depth_(frame_physical_depth), + frame_device_pixel_ratio_(frame_device_pixel_ratio), rasterizer_tracing_threshold_(0), checkerboard_raster_cache_images_(false), checkerboard_offscreen_layers_(false) {} -LayerTree::~LayerTree() = default; - void LayerTree::RecordBuildTime(fml::TimePoint start) { build_start_ = start; build_finish_ = fml::TimePoint::Now(); @@ -42,7 +44,9 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame, frame.context().raster_time(), frame.context().ui_time(), frame.context().texture_registry(), - checkerboard_offscreen_layers_}; + checkerboard_offscreen_layers_, + frame_physical_depth_, + frame_device_pixel_ratio_}; root_layer_->Preroll(&context, frame.root_surface_transformation()); } @@ -51,12 +55,22 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame, void LayerTree::UpdateScene(SceneUpdateContext& context, scenic::ContainerNode& container) { TRACE_EVENT0("flutter", "LayerTree::UpdateScene"); + + // Ensure the context is aware of the view metrics. + context.set_dimensions(frame_size_, frame_physical_depth_, + frame_device_pixel_ratio_); + const auto& metrics = context.metrics(); + FML_DCHECK(metrics->scale_x > 0.0f); + FML_DCHECK(metrics->scale_y > 0.0f); + FML_DCHECK(metrics->scale_z > 0.0f); + SceneUpdateContext::Transform transform(context, // context 1.0f / metrics->scale_x, // X 1.0f / metrics->scale_y, // Y 1.0f / metrics->scale_z // Z ); + SceneUpdateContext::Frame frame( context, SkRRect::MakeRect( @@ -94,7 +108,9 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, frame.context().ui_time(), frame.context().texture_registry(), ignore_raster_cache ? nullptr : &frame.context().raster_cache(), - checkerboard_offscreen_layers_}; + checkerboard_offscreen_layers_, + frame_physical_depth_, + frame_device_pixel_ratio_}; if (root_layer_->needs_painting()) root_layer_->Paint(context); @@ -118,16 +134,18 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { root_surface_transformation.reset(); PrerollContext preroll_context{ - nullptr, // raster_cache (don't consult the cache) - nullptr, // gr_context (used for the raster cache) - nullptr, // external view embedder - unused_stack, // mutator stack - nullptr, // SkColorSpace* dst_color_space - kGiantRect, // SkRect cull_rect - unused_stopwatch, // frame time (dont care) - unused_stopwatch, // engine time (dont care) - unused_texture_registry, // texture registry (not supported) - false, // checkerboard_offscreen_layers + nullptr, // raster_cache (don't consult the cache) + nullptr, // gr_context (used for the raster cache) + nullptr, // external view embedder + unused_stack, // mutator stack + nullptr, // SkColorSpace* dst_color_space + kGiantRect, // SkRect cull_rect + unused_stopwatch, // frame time (dont care) + unused_stopwatch, // engine time (dont care) + unused_texture_registry, // texture registry (not supported) + false, // checkerboard_offscreen_layers + frame_physical_depth_, // maximum depth allowed for rendering + frame_device_pixel_ratio_ // ratio between logical and physical }; SkISize canvas_size = canvas->getBaseLayerSize(); @@ -139,11 +157,13 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { canvas, // canvas nullptr, nullptr, - unused_stopwatch, // frame time (dont care) - unused_stopwatch, // engine time (dont care) - unused_texture_registry, // texture registry (not supported) - nullptr, // raster cache - false // checkerboard offscreen layers + unused_stopwatch, // frame time (dont care) + unused_stopwatch, // engine time (dont care) + unused_texture_registry, // texture registry (not supported) + nullptr, // raster cache + false, // checkerboard offscreen layers + frame_physical_depth_, // maximum depth allowed for rendering + frame_device_pixel_ratio_ // ratio between logical and physical }; // Even if we don't have a root layer, we still need to create an empty diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 124b8a85dea45..488627362f11f 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -14,15 +14,15 @@ #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 { class LayerTree { public: - LayerTree(); - - ~LayerTree(); + LayerTree(const SkISize& frame_size, + float frame_physical_depth, + float frame_device_pixel_ratio); + ~LayerTree() = default; void Preroll(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache = false); @@ -44,8 +44,8 @@ class LayerTree { } const SkISize& frame_size() const { return frame_size_; } - - void set_frame_size(const SkISize& frame_size) { frame_size_ = frame_size; } + float frame_physical_depth() const { return frame_physical_depth_; } + float frame_device_pixel_ratio() const { return frame_device_pixel_ratio_; } void RecordBuildTime(fml::TimePoint begin_start); fml::TimePoint build_start() const { return build_start_; } @@ -71,18 +71,15 @@ class LayerTree { checkerboard_offscreen_layers_ = checkerboard; } - void set_device_pixel_ratio(double device_pixel_ratio) { - device_pixel_ratio_ = device_pixel_ratio; - } - - double device_pixel_ratio() const { return device_pixel_ratio_; } + double device_pixel_ratio() const { return frame_device_pixel_ratio_; } private: - SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels. - double device_pixel_ratio_ = 1.0; std::shared_ptr root_layer_; fml::TimePoint build_start_; fml::TimePoint build_finish_; + SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels. + float frame_physical_depth_; + float frame_device_pixel_ratio_ = 1.0f; // Logical / Physical pixels ratio. uint32_t rasterizer_tracing_threshold_; bool checkerboard_raster_cache_images_; bool checkerboard_offscreen_layers_; diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 21c9265ce00dd..44995b202f1d3 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -14,15 +14,11 @@ const SkScalar kLightRadius = 800; PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, SkColor shadow_color, - SkScalar device_pixel_ratio, - float viewport_depth, float elevation, const SkPath& path, Clip clip_behavior) : color_(color), shadow_color_(shadow_color), - device_pixel_ratio_(device_pixel_ratio), - viewport_depth_(viewport_depth), elevation_(elevation), path_(path), isRect_(false), @@ -100,11 +96,13 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context, // t = tangent of AOB, i.e., multiplier for elevation to extent SkRect bounds(path_.getBounds()); // tangent for x - double tx = (kLightRadius * device_pixel_ratio_ + bounds.width() * 0.5) / + double tx = (kLightRadius * context->frame_device_pixel_ratio + + bounds.width() * 0.5) / kLightHeight; // tangent for y - double ty = (kLightRadius * device_pixel_ratio_ + bounds.height() * 0.5) / - kLightHeight; + double ty = + (kLightRadius * context->frame_device_pixel_ratio + bounds.height() * 0.5) / + kLightHeight; bounds.outset(elevation_ * tx, elevation_ * ty); set_paint_bounds(bounds); #endif // defined(OS_FUCHSIA) @@ -130,7 +128,7 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) { // If we can't find an existing retained surface, create one. SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_, - total_elevation_, viewport_depth_, this); + total_elevation_, this); for (auto& layer : layers()) { if (layer->needs_painting()) { frame.AddPaintLayer(layer.get()); @@ -148,7 +146,7 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { if (elevation_ != 0) { DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_, - SkColorGetA(color_) != 0xff, device_pixel_ratio_); + SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio); } // Call drawPath without clip if possible for better performance. diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index f884fe02fc5bd..50a63bc62cc59 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -13,8 +13,6 @@ class PhysicalShapeLayer : public ContainerLayer { public: PhysicalShapeLayer(SkColor color, SkColor shadow_color, - SkScalar device_pixel_ratio, - float viewport_depth, float elevation, const SkPath& path, Clip clip_behavior); @@ -38,8 +36,6 @@ class PhysicalShapeLayer : public ContainerLayer { private: SkColor color_; SkColor shadow_color_; - SkScalar device_pixel_ratio_; - float viewport_depth_; float elevation_ = 0.0f; float total_elevation_ = 0.0f; SkPath path_; diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index 972424a2fec6d..4bb13ad7bc877 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -16,8 +16,6 @@ TEST(PhysicalShapeLayer, TotalElevation) { for (int i = 0; i < 4; i += 1) { layers[i] = std::make_shared(dummy_color, dummy_color, - 1.0f, // pixel ratio, - 1.0f, // depth (float)(i + 1), // elevation dummy_path, Clip::none); } @@ -40,6 +38,8 @@ TEST(PhysicalShapeLayer, TotalElevation) { unused_stopwatch, // engine time (dont care) unused_texture_registry, // texture registry (not supported) false, // checkerboard_offscreen_layers + 1.0f, // physical depth + 1.0f, // device pixel ratio 0.0f, // total elevation }; diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 0a2e084c96455..10a165498b4e8 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -174,7 +174,9 @@ void RasterCache::Prepare(PrerollContext* context, context->ui_time, context->texture_registry, context->has_platform_view ? nullptr : context->raster_cache, - context->checkerboard_offscreen_layers}; + context->checkerboard_offscreen_layers, + context->frame_physical_depth, + context->frame_device_pixel_ratio}; if (layer->needs_painting()) { layer->Paint(paintContext); } diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index 14190b5b5d631..01f73d2a09b2d 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -205,7 +205,9 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) { frame.context().ui_time(), frame.context().texture_registry(), &frame.context().raster_cache(), - false}; + false, + frame_physical_depth_, + frame_device_pixel_ratio_}; canvas->restoreToCount(1); canvas->save(); canvas->clear(task.background_color); @@ -294,13 +296,13 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, SkColor color, float local_elevation, float world_elevation, - float depth, Layer* layer) : Shape(context), rrect_(rrect), color_(color), 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 diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index d4a46055967f3..a9b4f73bf78bc 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -117,7 +117,6 @@ class SceneUpdateContext { SkColor color, float local_elevation = 0.0f, float parent_elevation = 0.0f, - float depth = 0.0f, Layer* layer = nullptr); virtual ~Frame(); @@ -152,6 +151,17 @@ class SceneUpdateContext { } const fuchsia::ui::gfx::MetricsPtr& metrics() const { return metrics_; } + void set_dimensions(const SkISize& frame_physical_size, + float frame_physical_depth, + float frame_device_pixel_ratio) { + frame_physical_size_ = frame_physical_size; + frame_physical_depth_ = frame_physical_depth; + frame_device_pixel_ratio_ = frame_device_pixel_ratio; + } + const SkISize& frame_size() const { return frame_physical_size_; } + float frame_physical_depth() const { return frame_physical_depth_; } + float frame_device_pixel_ratio() const { return frame_device_pixel_ratio_; } + // TODO(chinmaygarde): This method must submit the surfaces as soon as paint // tasks are done. However, given that there is no support currently for // Vulkan semaphores, we need to submit all the surfaces after an explicit @@ -225,6 +235,10 @@ class SceneUpdateContext { SurfaceProducer* const surface_producer_; fuchsia::ui::gfx::MetricsPtr metrics_; + SkISize frame_physical_size_; + float frame_physical_depth_ = 0.0f; + float frame_device_pixel_ratio_ = + 1.0f; // Ratio between logical and physical pixels. std::vector paint_tasks_; diff --git a/lib/ui/compositing/scene.cc b/lib/ui/compositing/scene.cc index fd3e86c7e5176..d02a232ac0433 100644 --- a/lib/ui/compositing/scene.cc +++ b/lib/ui/compositing/scene.cc @@ -7,6 +7,8 @@ #include "flutter/fml/trace_event.h" #include "flutter/lib/ui/painting/image.h" #include "flutter/lib/ui/painting/picture.h" +#include "flutter/lib/ui/ui_dart_state.h" +#include "flutter/lib/ui/window/window.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/tonic/converter/dart_converter.h" @@ -36,13 +38,19 @@ fml::RefPtr Scene::create(std::shared_ptr rootLayer, Scene::Scene(std::shared_ptr rootLayer, uint32_t rasterizerTracingThreshold, bool checkerboardRasterCacheImages, - bool checkerboardOffscreenLayers) - : m_layerTree(new flutter::LayerTree()) { - m_layerTree->set_root_layer(std::move(rootLayer)); - m_layerTree->set_rasterizer_tracing_threshold(rasterizerTracingThreshold); - m_layerTree->set_checkerboard_raster_cache_images( + bool checkerboardOffscreenLayers) { + auto viewport_metrics = UIDartState::Current()->window()->viewport_metrics(); + + layer_tree_ = std::make_unique( + SkISize::Make(viewport_metrics.physical_width, + viewport_metrics.physical_height), + static_cast(viewport_metrics.physical_depth), + static_cast(viewport_metrics.device_pixel_ratio)); + layer_tree_->set_root_layer(std::move(rootLayer)); + layer_tree_->set_rasterizer_tracing_threshold(rasterizerTracingThreshold); + layer_tree_->set_checkerboard_raster_cache_images( checkerboardRasterCacheImages); - m_layerTree->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers); + layer_tree_->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers); } Scene::~Scene() {} @@ -56,11 +64,11 @@ Dart_Handle Scene::toImage(uint32_t width, Dart_Handle raw_image_callback) { TRACE_EVENT0("flutter", "Scene::toImage"); - if (!m_layerTree) { + if (!layer_tree_) { return tonic::ToDart("Scene did not contain a layer tree."); } - auto picture = m_layerTree->Flatten(SkRect::MakeWH(width, height)); + auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height)); if (!picture) { return tonic::ToDart("Could not flatten scene into a layer tree."); } @@ -69,7 +77,7 @@ Dart_Handle Scene::toImage(uint32_t width, } std::unique_ptr Scene::takeLayerTree() { - return std::move(m_layerTree); + return std::move(layer_tree_); } } // namespace flutter diff --git a/lib/ui/compositing/scene.h b/lib/ui/compositing/scene.h index 2d280a534db63..42c972d8d4ee3 100644 --- a/lib/ui/compositing/scene.h +++ b/lib/ui/compositing/scene.h @@ -45,7 +45,7 @@ class Scene : public RefCountedDartWrappable { bool checkerboardRasterCacheImages, bool checkerboardOffscreenLayers); - std::unique_ptr m_layerTree; + std::unique_ptr layer_tree_; }; } // namespace flutter diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 5b7148803c2c2..61b74f743a9f4 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -23,8 +23,6 @@ #include "flutter/fml/build_config.h" #include "flutter/lib/ui/painting/matrix.h" #include "flutter/lib/ui/painting/shader.h" -#include "flutter/lib/ui/ui_dart_state.h" -#include "flutter/lib/ui/window/window.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/tonic/converter/dart_converter.h" #include "third_party/tonic/dart_args.h" @@ -176,12 +174,6 @@ fml::RefPtr SceneBuilder::pushPhysicalShape(const CanvasPath* path, int clipBehavior) { auto layer = std::make_shared( static_cast(color), static_cast(shadow_color), - static_cast(UIDartState::Current() - ->window() - ->viewport_metrics() - .device_pixel_ratio), - static_cast( - UIDartState::Current()->window()->viewport_metrics().physical_depth), static_cast(elevation), path->path(), static_cast(clipBehavior)); PushLayer(layer); diff --git a/lib/ui/window/viewport_metrics.cc b/lib/ui/window/viewport_metrics.cc index f18972992189a..0b6dab6d4c1e0 100644 --- a/lib/ui/window/viewport_metrics.cc +++ b/lib/ui/window/viewport_metrics.cc @@ -4,8 +4,9 @@ #include "flutter/lib/ui/window/viewport_metrics.h" +#include "flutter/fml/logging.h" + namespace flutter { -ViewportMetrics::ViewportMetrics() = default; ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio, double p_physical_width, @@ -39,6 +40,10 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio, physical_system_gesture_inset_bottom( p_physical_system_gesture_inset_bottom), physical_system_gesture_inset_left(p_physical_system_gesture_inset_left) { + // Ensure we don't have nonsensical dimensions. + FML_DCHECK(physical_width >= 0); + FML_DCHECK(physical_height >= 0); + FML_DCHECK(device_pixel_ratio > 0); } ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio, @@ -68,8 +73,11 @@ 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), physical_view_inset_front(p_physical_view_inset_front), - physical_view_inset_back(p_physical_view_inset_back) {} - -ViewportMetrics::ViewportMetrics(const ViewportMetrics& other) = default; + physical_view_inset_back(p_physical_view_inset_back) { + // Ensure we don't have nonsensical dimensions. + FML_DCHECK(physical_width >= 0); + FML_DCHECK(physical_height >= 0); + FML_DCHECK(device_pixel_ratio > 0); +} } // namespace flutter diff --git a/lib/ui/window/viewport_metrics.h b/lib/ui/window/viewport_metrics.h index 5ca8b78eaa064..f60adbfcee110 100644 --- a/lib/ui/window/viewport_metrics.h +++ b/lib/ui/window/viewport_metrics.h @@ -16,7 +16,8 @@ namespace flutter { static const double kUnsetDepth = 1.7976931348623157e+308; struct ViewportMetrics { - ViewportMetrics(); + ViewportMetrics() = default; + ViewportMetrics(const ViewportMetrics& other) = default; // Create a 2D ViewportMetrics instance. ViewportMetrics(double p_device_pixel_ratio, @@ -51,8 +52,6 @@ struct ViewportMetrics { 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; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 38b034d52d0d0..870520f094df2 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -437,13 +437,12 @@ void Engine::Render(std::unique_ptr layer_tree) { if (!layer_tree) return; - SkISize frame_size = SkISize::Make(viewport_metrics_.physical_width, - viewport_metrics_.physical_height); - if (frame_size.isEmpty()) + // Ensure frame dimensions are sane. + if (layer_tree->frame_size().isEmpty() || + layer_tree->frame_physical_depth() <= 0.0f || + layer_tree->frame_device_pixel_ratio() <= 0.0f) return; - layer_tree->set_frame_size(frame_size); - layer_tree->set_device_pixel_ratio(viewport_metrics_.device_pixel_ratio); animator_->Render(std::move(layer_tree)); } diff --git a/shell/common/persistent_cache_unittests.cc b/shell/common/persistent_cache_unittests.cc index 62b36e786875b..4948a3359bc69 100644 --- a/shell/common/persistent_cache_unittests.cc +++ b/shell/common/persistent_cache_unittests.cc @@ -56,7 +56,7 @@ TEST_F(ShellTest, CacheSkSLWorks) { SkPath path; path.addCircle(50, 50, 20); auto physical_shape_layer = std::make_shared( - SK_ColorRED, SK_ColorBLUE, 1.0f, 1.0f, 1.0f, path, Clip::antiAlias); + SK_ColorRED, SK_ColorBLUE, 1.0f, path, Clip::antiAlias); root->Add(physical_shape_layer); }; PumpOneFrame(shell.get(), 100, 100, builder); diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index 3fe5a2b9e0f87..acb46da6904a9 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -139,14 +139,19 @@ void ShellTest::PumpOneFrame(Shell* shell, double width, double height, LayerTreeBuilder builder) { + PumpOneFrame(shell, flutter::ViewportMetrics {1, width, height, flutter::kUnsetDepth, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, std::move(builder)); +} + +void ShellTest::PumpOneFrame(Shell* shell, + flutter::ViewportMetrics viewport_metrics, + LayerTreeBuilder builder) { // Set viewport to nonempty, and call Animator::BeginFrame to make the layer // tree pipeline nonempty. Without either of this, the layer tree below // won't be rasterized. fml::AutoResetWaitableEvent latch; shell->GetTaskRunners().GetUITaskRunner()->PostTask( - [&latch, engine = shell->weak_engine_, width, height]() { - engine->SetViewportMetrics( - {1, width, height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + [&latch, engine = shell->weak_engine_, viewport_metrics]() { + engine->SetViewportMetrics(std::move(viewport_metrics)); engine->animator_->BeginFrame(fml::TimePoint::Now(), fml::TimePoint::Now()); latch.Signal(); @@ -158,7 +163,14 @@ void ShellTest::PumpOneFrame(Shell* shell, fml::WeakPtr runtime_delegate = shell->weak_engine_; shell->GetTaskRunners().GetUITaskRunner()->PostTask( [&latch, runtime_delegate, &builder]() { - auto layer_tree = std::make_unique(); + auto viewport_metrics = + UIDartState::Current()->window()->viewport_metrics(); + + auto layer_tree = std::make_unique( + SkISize::Make(viewport_metrics.physical_width, + viewport_metrics.physical_height), + static_cast(viewport_metrics.physical_depth), + static_cast(viewport_metrics.device_pixel_ratio)); SkMatrix identity; identity.setIdentity(); auto root_layer = std::make_shared(identity); diff --git a/shell/common/shell_test.h b/shell/common/shell_test.h index 27d32f058ae0e..d52907804d447 100644 --- a/shell/common/shell_test.h +++ b/shell/common/shell_test.h @@ -57,10 +57,10 @@ class ShellTest : public ThreadTest { using LayerTreeBuilder = std::function root)>; static void PumpOneFrame(Shell* shell, - double width = 1, - double height = 1, - LayerTreeBuilder = {}); - + double width = 1, + double height = 1, + LayerTreeBuilder = {}); + static void PumpOneFrame(Shell* shell, flutter::ViewportMetrics viewport_metrics, LayerTreeBuilder = {}); static void DispatchFakePointerData(Shell* shell); // Declare |UnreportedTimingsCount|, |GetNeedsReportTimings| and diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 0146619cce4cf..9e2f6a07788ff 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -603,6 +603,23 @@ TEST_F(ShellTest, WaitForFirstFrame) { DestroyShell(std::move(shell)); } +TEST_F(ShellTest, WaitForFirstFrameZeroSizeFrame) { + auto settings = CreateSettingsForFixture(); + std::unique_ptr shell = CreateShell(settings); + + // Create the surface needed by rasterizer + PlatformViewNotifyCreated(shell.get()); + + auto configuration = RunConfiguration::InferFromSettings(settings); + configuration.SetEntrypoint("emptyMain"); + + RunEngine(shell.get(), std::move(configuration)); + PumpOneFrame(shell.get(), {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + fml::Status result = + shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000)); + ASSERT_EQ(result.code(), fml::StatusCode::kDeadlineExceeded); +} + TEST_F(ShellTest, WaitForFirstFrameTimeout) { auto settings = CreateSettingsForFixture(); std::unique_ptr shell = CreateShell(settings); diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index 643034888aaa9..f74781df22af4 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -1604,7 +1604,6 @@ TEST_F(EmbedderTest, CustomCompositorMustWorkWithCustomTaskRunner) { event.width = 800; event.height = 600; event.pixel_ratio = 1.0; - ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); From 60390d6e729b426e8ae0167a8c2c8c7ca18bdfc8 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Thu, 3 Oct 2019 22:16:21 -0700 Subject: [PATCH 03/11] Maintain layer stack inside of SceneBuilder --- flow/layers/container_layer.cc | 5 +- flow/layers/container_layer.h | 2 +- flow/layers/layer.cc | 7 ++- flow/layers/layer.h | 9 +--- lib/ui/compositing/scene_builder.cc | 72 ++++++++++++----------------- lib/ui/compositing/scene_builder.h | 13 +++--- lib/ui/painting/engine_layer.cc | 2 - lib/ui/painting/engine_layer.h | 2 +- 8 files changed, 46 insertions(+), 66 deletions(-) diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index d5c6a2a03a34a..ea20800d05c80 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -11,7 +11,6 @@ ContainerLayer::ContainerLayer() {} ContainerLayer::~ContainerLayer() = default; void ContainerLayer::Add(std::shared_ptr layer) { - layer->set_parent(this); layers_.push_back(std::move(layer)); } @@ -50,6 +49,10 @@ void ContainerLayer::PrerollChildren(PrerollContext* context, context->has_platform_view = child_has_platform_view; } +void ContainerLayer::Paint(PaintContext& context) const { + PaintChildren(context); +} + void ContainerLayer::PaintChildren(PaintContext& context) const { FML_DCHECK(needs_painting()); diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index ef1c03328d1df..e484fa3c3c40f 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -18,10 +18,10 @@ class ContainerLayer : public Layer { void Add(std::shared_ptr layer); void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - #if defined(OS_FUCHSIA) void UpdateScene(SceneUpdateContext& context) override; #endif // defined(OS_FUCHSIA) + void Paint(PaintContext& context) const override; const std::vector>& layers() const { return layers_; } diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index b729f582a0a9a..5ad6a6bee1499 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -10,10 +10,9 @@ namespace flutter { Layer::Layer() - : parent_(nullptr), - needs_system_composite_(false), - paint_bounds_(SkRect::MakeEmpty()), - unique_id_(NextUniqueID()) {} + : paint_bounds_(SkRect::MakeEmpty()), + unique_id_(NextUniqueID()), + needs_system_composite_(false) {} Layer::~Layer() = default; diff --git a/flow/layers/layer.h b/flow/layers/layer.h index ba91353140889..a9c4a3aa818ce 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -42,8 +42,6 @@ static constexpr SkRect kGiantRect = SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F); // This should be an exact copy of the Clip enum in painting.dart. enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer }; -class ContainerLayer; - struct PrerollContext { RasterCache* raster_cache; GrContext* gr_context; @@ -137,10 +135,6 @@ class Layer { virtual void UpdateScene(SceneUpdateContext& context); #endif - ContainerLayer* parent() const { return parent_; } - - void set_parent(ContainerLayer* parent) { parent_ = parent; } - bool needs_system_composite() const { return needs_system_composite_; } void set_needs_system_composite(bool value) { needs_system_composite_ = value; @@ -159,10 +153,9 @@ class Layer { uint64_t unique_id() const { return unique_id_; } private: - ContainerLayer* parent_; - bool needs_system_composite_; SkRect paint_bounds_; uint64_t unique_id_; + bool needs_system_composite_; static uint64_t NextUniqueID(); diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 61b74f743a9f4..216e1c9284874 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -78,7 +78,12 @@ void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) { }); } -SceneBuilder::SceneBuilder() = default; +SceneBuilder::SceneBuilder() { + // Add a ContainerLayer as the root layer, so that AddLayer operations are + // always valid. + PushLayer(std::make_shared()); +} + SceneBuilder::~SceneBuilder() = default; fml::RefPtr SceneBuilder::pushTransform( @@ -181,33 +186,24 @@ fml::RefPtr SceneBuilder::pushPhysicalShape(const CanvasPath* path, } void SceneBuilder::addRetained(fml::RefPtr retainedLayer) { - if (!current_layer_) { - return; - } - current_layer_->Add(retainedLayer->Layer()); + AddLayer(retainedLayer->Layer()); } void SceneBuilder::pop() { - if (!current_layer_) { - return; - } - current_layer_ = current_layer_->parent(); + PopLayer(); } void SceneBuilder::addPicture(double dx, double dy, Picture* picture, int hints) { - if (!current_layer_) { - return; - } SkPoint offset = SkPoint::Make(dx, dy); SkRect pictureRect = picture->picture()->cullRect(); pictureRect.offset(offset.x(), offset.y()); auto layer = std::make_unique( offset, UIDartState::CreateGPUObject(picture->picture()), !!(hints & 1), !!(hints & 2)); - current_layer_->Add(std::move(layer)); + AddLayer(std::move(layer)); } void SceneBuilder::addTexture(double dx, @@ -216,12 +212,9 @@ void SceneBuilder::addTexture(double dx, double height, int64_t textureId, bool freeze) { - if (!current_layer_) { - return; - } auto layer = std::make_unique( SkPoint::Make(dx, dy), SkSize::Make(width, height), textureId, freeze); - current_layer_->Add(std::move(layer)); + AddLayer(std::move(layer)); } void SceneBuilder::addPlatformView(double dx, @@ -229,12 +222,9 @@ void SceneBuilder::addPlatformView(double dx, double width, double height, int64_t viewId) { - if (!current_layer_) { - return; - } auto layer = std::make_unique( SkPoint::Make(dx, dy), SkSize::Make(width, height), viewId); - current_layer_->Add(std::move(layer)); + AddLayer(std::move(layer)); } #if defined(OS_FUCHSIA) @@ -244,13 +234,10 @@ void SceneBuilder::addChildScene(double dx, double height, SceneHost* sceneHost, bool hitTestable) { - if (!current_layer_) { - return; - } auto layer = std::make_unique( sceneHost->id(), SkPoint::Make(dx, dy), SkSize::Make(width, height), hitTestable); - current_layer_->Add(std::move(layer)); + AddLayer(std::move(layer)); } #endif // defined(OS_FUCHSIA) @@ -259,14 +246,11 @@ void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, double right, double top, double bottom) { - if (!current_layer_) { - return; - } SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); auto layer = std::make_unique(enabledOptions); layer->set_paint_bounds(rect); - current_layer_->Add(std::move(layer)); + AddLayer(std::move(layer)); } void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) { @@ -282,29 +266,33 @@ void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) { } fml::RefPtr SceneBuilder::build() { + FML_DCHECK(layer_stack_.size() >= 1); + fml::RefPtr scene = Scene::create( - std::move(root_layer_), rasterizer_tracing_threshold_, + layer_stack_[0], rasterizer_tracing_threshold_, checkerboard_raster_cache_images_, checkerboard_offscreen_layers_); - ClearDartWrapper(); + ClearDartWrapper(); // may delete this object. return scene; } -void SceneBuilder::PushLayer(std::shared_ptr layer) { +void SceneBuilder::AddLayer(std::shared_ptr layer) { FML_DCHECK(layer); - if (!root_layer_) { - root_layer_ = std::move(layer); - current_layer_ = root_layer_.get(); - return; + if (!layer_stack_.empty()) { + layer_stack_.back()->Add(std::move(layer)); } +} - if (!current_layer_) { - return; - } +void SceneBuilder::PushLayer(std::shared_ptr layer) { + AddLayer(layer); + layer_stack_.push_back(std::move(layer)); +} - flutter::ContainerLayer* newLayer = layer.get(); - current_layer_->Add(std::move(layer)); - current_layer_ = newLayer; +void SceneBuilder::PopLayer() { + // We never pop the root layer, so that AddLayer operations are always valid. + if (layer_stack_.size() > 1) { + layer_stack_.pop_back(); + } } } // namespace flutter diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index d378876d960a2..a634087174e2f 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -8,8 +8,9 @@ #include #include -#include +#include +#include "flutter/flow/layers/container_layer.h" #include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/dart_wrapper.h" #include "flutter/lib/ui/painting/color_filter.h" @@ -35,7 +36,6 @@ class SceneBuilder : public RefCountedDartWrappable { static fml::RefPtr create() { return fml::MakeRefCounted(); } - ~SceneBuilder() override; fml::RefPtr pushTransform(tonic::Float64List& matrix4); @@ -98,7 +98,6 @@ class SceneBuilder : public RefCountedDartWrappable { #endif void setRasterizerTracingThreshold(uint32_t frameInterval); - void setCheckerboardRasterCacheImages(bool checkerboard); void setCheckerboardOffscreenLayers(bool checkerboard); @@ -109,15 +108,15 @@ class SceneBuilder : public RefCountedDartWrappable { private: SceneBuilder(); - std::shared_ptr root_layer_; - flutter::ContainerLayer* current_layer_ = nullptr; + void AddLayer(std::shared_ptr layer); + void PushLayer(std::shared_ptr layer); + void PopLayer(); + std::vector> layer_stack_; int rasterizer_tracing_threshold_ = 0; bool checkerboard_raster_cache_images_ = false; bool checkerboard_offscreen_layers_ = false; - void PushLayer(std::shared_ptr layer); - FML_DISALLOW_COPY_AND_ASSIGN(SceneBuilder); }; diff --git a/lib/ui/painting/engine_layer.cc b/lib/ui/painting/engine_layer.cc index 7ac9c98497f41..0868b42cc2928 100644 --- a/lib/ui/painting/engine_layer.cc +++ b/lib/ui/painting/engine_layer.cc @@ -4,8 +4,6 @@ #include "flutter/lib/ui/painting/engine_layer.h" -#include "flutter/flow/layers/container_layer.h" - #include "third_party/tonic/converter/dart_converter.h" #include "third_party/tonic/dart_args.h" #include "third_party/tonic/dart_binding_macros.h" diff --git a/lib/ui/painting/engine_layer.h b/lib/ui/painting/engine_layer.h index 1dc565c5193c2..a679ef2fe50f3 100644 --- a/lib/ui/painting/engine_layer.h +++ b/lib/ui/painting/engine_layer.h @@ -7,7 +7,7 @@ #include "flutter/lib/ui/dart_wrapper.h" -#include "flutter/flow/layers/layer.h" +#include "flutter/flow/layers/container_layer.h" namespace tonic { class DartLibraryNatives; From dc492a0f32b02205d2f25397d5355b4798e1abaf Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 11 Nov 2019 11:00:34 -0800 Subject: [PATCH 04/11] Remove EnsureSingleChild --- flow/layers/container_layer.cc | 2 +- flow/layers/container_layer.h | 2 +- flow/layers/opacity_layer.cc | 57 ++++++++++++++++------------------ flow/layers/opacity_layer.h | 14 +++------ 4 files changed, 33 insertions(+), 42 deletions(-) diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index ea20800d05c80..97d20c0ec4959 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -11,7 +11,7 @@ ContainerLayer::ContainerLayer() {} ContainerLayer::~ContainerLayer() = default; void ContainerLayer::Add(std::shared_ptr layer) { - layers_.push_back(std::move(layer)); + layers_.emplace_back(std::move(layer)); } void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index e484fa3c3c40f..f3b0bb6a837f3 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -15,7 +15,7 @@ class ContainerLayer : public Layer { ContainerLayer(); ~ContainerLayer() override; - void Add(std::shared_ptr layer); + virtual void Add(std::shared_ptr layer); void Preroll(PrerollContext* context, const SkMatrix& matrix) override; #if defined(OS_FUCHSIA) diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index a27981650d2bf..dc24a6a541ca4 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -4,37 +4,33 @@ #include "flutter/flow/layers/opacity_layer.h" -#include "flutter/flow/layers/transform_layer.h" +#include "flutter/fml/trace_event.h" +#include "third_party/skia/include/core/SkPaint.h" namespace flutter { OpacityLayer::OpacityLayer(int alpha, const SkPoint& offset) - : alpha_(alpha), offset_(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 + // save the costly saveLayer. + // + // Any children will be actually added as children of this empty + // ContainerLayer. + ContainerLayer::Add(std::make_shared()); +} OpacityLayer::~OpacityLayer() = default; -void OpacityLayer::EnsureSingleChild() { - FML_DCHECK(layers().size() > 0); // OpacityLayer should never be a leaf - - if (layers().size() == 1) { - return; - } - - // Be careful: SkMatrix's default constructor doesn't initialize the matrix to - // identity. Hence we have to explicitly call SkMatrix::setIdentity. - SkMatrix identity; - identity.setIdentity(); - auto new_child = std::make_shared(identity); - - for (auto& child : layers()) { - new_child->Add(child); - } - ClearChildren(); - Add(new_child); +void OpacityLayer::Add(std::shared_ptr layer) { + GetChildContainer()->Add(std::move(layer)); } void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { - EnsureSingleChild(); + ContainerLayer* container = GetChildContainer(); + FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf. + SkMatrix child_matrix = matrix; child_matrix.postTranslate(offset_.fX, offset_.fY); context->mutators_stack.PushTransform( @@ -44,16 +40,14 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { context->mutators_stack.Pop(); context->mutators_stack.Pop(); set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY)); - // See |EnsureSingleChild|. - FML_DCHECK(layers().size() == 1); + if (!context->has_platform_view && context->raster_cache && SkRect::Intersects(context->cull_rect, paint_bounds())) { - Layer* child = layers()[0].get(); SkMatrix ctm = child_matrix; #ifndef SUPPORT_FRACTIONAL_TRANSLATION ctm = RasterCache::GetIntegralTransCTM(ctm); #endif - context->raster_cache->Prepare(context, child, ctm); + context->raster_cache->Prepare(context, container, ctm); } } @@ -72,13 +66,10 @@ void OpacityLayer::Paint(PaintContext& context) const { context.leaf_nodes_canvas->getTotalMatrix())); #endif - // See |EnsureSingleChild|. - FML_DCHECK(layers().size() == 1); - if (context.raster_cache) { + ContainerLayer* container = GetChildContainer(); const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix(); - RasterCacheResult child_cache = - context.raster_cache->Get(layers()[0].get(), ctm); + RasterCacheResult child_cache = context.raster_cache->Get(container, ctm); if (child_cache.is_valid()) { child_cache.draw(*context.leaf_nodes_canvas, &paint); return; @@ -104,4 +95,10 @@ void OpacityLayer::Paint(PaintContext& context) const { PaintChildren(context); } +ContainerLayer* OpacityLayer::GetChildContainer() const { + FML_DCHECK(layers().size() == 1); + + return static_cast(layers()[0].get()); +} + } // namespace flutter diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index 795d8841ba6ed..c8ecad959bb82 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -28,6 +28,8 @@ class OpacityLayer : public ContainerLayer { OpacityLayer(int alpha, const SkPoint& offset); ~OpacityLayer() override; + void Add(std::shared_ptr layer) override; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; @@ -36,19 +38,11 @@ class OpacityLayer : public ContainerLayer { // session scene hierarchy. private: + ContainerLayer* GetChildContainer() const; + int alpha_; SkPoint offset_; - // Restructure (if necessary) OpacityLayer to have only one child. - // - // This is needed to ensure that retained rendering can always be applied to - // save the costly saveLayer. - // - // If there are multiple children, this creates a new identity TransformLayer, - // sets all children to be the TransformLayer's children, and sets that - // TransformLayer as the single child of this OpacityLayer. - void EnsureSingleChild(); - FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer); }; From 301db02102cb2dfadf5f307bb98cb22cf0cede29 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Fri, 4 Oct 2019 16:49:35 -0700 Subject: [PATCH 05/11] Centralize system-composite and elevation logic --- flow/layers/container_layer.cc | 104 +++++++++- flow/layers/container_layer.h | 46 +++++ flow/layers/layer_tree.cc | 2 +- flow/layers/physical_shape_layer.cc | 178 ++++++++---------- flow/layers/physical_shape_layer.h | 44 +++-- flow/layers/physical_shape_layer_unittests.cc | 12 +- flow/scene_update_context.cc | 22 +-- flow/scene_update_context.h | 3 +- 8 files changed, 263 insertions(+), 148 deletions(-) diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index 97d20c0ec4959..3ee7356470e8b 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -5,6 +5,26 @@ #include "flutter/flow/layers/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 ContainerLayer::ContainerLayer() {} @@ -74,9 +94,9 @@ void ContainerLayer::UpdateScene(SceneUpdateContext& context) { void ContainerLayer::UpdateSceneChildren(SceneUpdateContext& context) { FML_DCHECK(needs_system_composite()); - // Paint all of the layers which need to be drawn into the container. - // These may be flattened down to a containing - for (auto& layer : layers_) { + // Update all of the Layers which are part of the container. This may cause + // additional child |Frame|s to be created. + for (auto& layer : layers()) { if (layer->needs_system_composite()) { layer->UpdateScene(context); } @@ -85,4 +105,82 @@ void ContainerLayer::UpdateSceneChildren(SceneUpdateContext& context) { #endif // defined(OS_FUCHSIA) +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_; +} + +FuchsiaSystemCompositedContainerLayer::FuchsiaSystemCompositedContainerLayer(SkColor color, float elevation) + : ElevatedContainerLayer(elevation), + color_(color) {} + +void FuchsiaSystemCompositedContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + TRACE_EVENT0("flutter", "SystemCompositedContainerLayer::Preroll"); +#if !defined(OS_FUCHSIA) + FML_NOTIMPLEMENTED(); +#endif // !defined(OS_FUCHSIA) + + // System-composite this layer. + set_needs_system_composite(true); + + ElevatedContainerLayer::Preroll(context, matrix); +} + +void FuchsiaSystemCompositedContainerLayer::Paint(PaintContext& context) const { + TRACE_EVENT0("flutter", "SystemCompositedContainerLayer::Paint"); +#if !defined(OS_FUCHSIA) + FML_NOTIMPLEMENTED(); +#endif // !defined(OS_FUCHSIA) + + // TODO: hole punch + // If this is actually called, it's because flow is attempting to paint this + // layer onto the frame behind it which gives us a chance to hole-punch +} + +#if defined(OS_FUCHSIA) + +void FuchsiaSystemCompositedContainerLayer::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)) { + 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; + } + + SceneUpdateContext::Frame frame(context, rrect_, color_, + elevation(), this); + // Paint the child layers into the Frame. + for (auto& layer : layers()) { + if (layer->needs_painting()) { + frame.AddPaintLayer(layer.get()); + } + } + + ContainerLayer::UpdateScene(context); +} + +#endif // defined(OS_FUCHSIA) + } // namespace flutter diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index f3b0bb6a837f3..91d730dc57604 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -44,6 +44,52 @@ class ContainerLayer : public Layer { FML_DISALLOW_COPY_AND_ASSIGN(ContainerLayer); }; +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); +}; + +class FuchsiaSystemCompositedContainerLayer : public ElevatedContainerLayer { + public: + static bool should_system_composite() { return true; } + + FuchsiaSystemCompositedContainerLayer(SkColor color, float elevation); + ~FuchsiaSystemCompositedContainerLayer() override = default; + + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context) override; +#endif // defined(OS_FUCHSIA) + void Paint(PaintContext& context) const override; + + void set_dimensions(SkRRect rrect) { + rrect_ = rrect; + } + + SkColor color() const { return color_; } + + private: + SkRRect rrect_ = SkRRect::MakeEmpty(); + SkColor color_ = SK_ColorTRANSPARENT; + + FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaSystemCompositedContainerLayer); +}; + } // namespace flutter #endif // FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_ diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index a86d184a04533..77d6fb01d765e 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -75,7 +75,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, context, SkRRect::MakeRect( SkRect::MakeWH(frame_size_.width(), frame_size_.height())), - SK_ColorTRANSPARENT); + SK_ColorTRANSPARENT, /* elevation */ 0.0f); if (root_layer_->needs_system_composite()) { root_layer_->UpdateScene(context); } diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 44995b202f1d3..5e27eb6b8e1c4 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -17,22 +17,23 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, float elevation, const SkPath& path, Clip clip_behavior) - : color_(color), + : PhysicalShapeLayerBase(color, elevation), shadow_color_(shadow_color), - elevation_(elevation), path_(path), - isRect_(false), clip_behavior_(clip_behavior) { + // If rendering as a separate frame using the system compositor, then make + // sure to set up the properties needed to do so. +#if defined(OS_FUCHSIA) SkRect rect; + SkRRect rrect; if (path.isRect(&rect)) { - isRect_ = true; - frameRRect_ = SkRRect::MakeRect(rect); - } else if (path.isRRect(&frameRRect_)) { - isRect_ = frameRRect_.isRect(); + rrect = SkRRect::MakeRect(rect); + } else if (path.isRRect(&rrect)) { + // Nothing needed here, as isRRect will fill in frameRRect_ already. } else if (path.isOval(&rect)) { // isRRect returns false for ovals, so we need to explicitly check isOval // as well. - frameRRect_ = SkRRect::MakeOval(rect); + rrect = SkRRect::MakeOval(rect); } else { // Scenic currently doesn't provide an easy way to create shapes from // arbitrary paths. @@ -40,118 +41,95 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, // default to use the bounding rectangle. // TODO(amirh): fix this once we have a way to create a Scenic shape from // an SkPath. - frameRRect_ = SkRRect::MakeRect(path.getBounds()); + rrect = SkRRect::MakeRect(path.getBounds()); } -} -PhysicalShapeLayer::~PhysicalShapeLayer() = default; + set_dimensions(rrect); +#endif +} 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); - context->total_elevation -= elevation_; - - if (elevation_ == 0) { - set_paint_bounds(path_.getBounds()); - } else { -#if defined(OS_FUCHSIA) - // Let the system compositor draw all shadows for us. - set_needs_system_composite(true); -#else - // 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. - // The offset is calculated as follows: - - // .--- (kLightRadius) - // -------/ (light) - // | / - // | / - // |/ - // |O - // /| (kLightHeight) - // / | - // / | - // / | - // / | - // ------------- (layer) - // /| | - // / | | (elevation) - // A / | |B - // ------------------------------------------------ (canvas) - // --- (extent of shadow) - // - // E = lt } t = (r + w/2)/h - // } => - // r + w/2 = ht } E = (l/h)(r + w/2) - // - // Where: E = extent of shadow - // l = elevation of layer - // r = radius of the light source - // w = width of the layer - // h = light height - // t = tangent of AOB, i.e., multiplier for elevation to extent - SkRect bounds(path_.getBounds()); - // tangent for x - double tx = (kLightRadius * context->frame_device_pixel_ratio + - bounds.width() * 0.5) / - kLightHeight; - // tangent for y - double ty = - (kLightRadius * context->frame_device_pixel_ratio + bounds.height() * 0.5) / - kLightHeight; - bounds.outset(elevation_ * tx, elevation_ * ty); - set_paint_bounds(bounds); -#endif // defined(OS_FUCHSIA) - } -} + PhysicalShapeLayerBase::Preroll(context, matrix); + set_paint_bounds(path_.getBounds()); // Ignore children bounds; use the path. -#if defined(OS_FUCHSIA) - -void PhysicalShapeLayer::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 PhysicalShapeLayer::Paint. - LayerRasterCacheKey key(unique_id(), context.Matrix()); - if (context.HasRetainedNode(key)) { - const scenic::EntityNode& retained_node = context.GetRetainedNode(key); - FML_DCHECK(context.top_entity()); - FML_DCHECK(retained_node.session() == context.session()); - context.top_entity()->entity_node().AddChild(retained_node); + // If the elevation is 0, we are done. Shadows won't be drawn. + if (elevation() == 0) { + set_needs_system_composite(false); // No need for system composite here. return; } - // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_, - total_elevation_, this); - for (auto& layer : layers()) { - if (layer->needs_painting()) { - frame.AddPaintLayer(layer.get()); - } + // The system compositor can handle shadows if it is being used. + if (PhysicalShapeLayerBase::should_system_composite()) { + return; } - UpdateSceneChildren(context); + // 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. + // The offset is calculated as follows: + // .--- (kLightRadius) + // -------/ (light) + // | / + // | / + // |/ + // |O + // /| (kLightHeight) + // / | + // / | + // / | + // / | + // ------------- (layer) + // /| | + // / | | (elevation) + // A / | |B + // ------------------------------------------------ (canvas) + // --- (extent of shadow) + // + // E = lt } t = (r + w/2)/h + // } => + // r + w/2 = ht } E = (l/h)(r + w/2) + // + // Where: E = extent of shadow + // l = elevation of layer + // r = radius of the light source + // w = width of the layer + // h = light height + // t = tangent of AOB, i.e., multiplier for elevation to extent + SkRect bounds(paint_bounds()); + // tangent for x + double tx = (kLightRadius * context->frame_device_pixel_ratio + bounds.width() * 0.5) / kLightHeight; + // tangent for y + double ty = (kLightRadius * context->frame_device_pixel_ratio + bounds.height() * 0.5) / kLightHeight; + bounds.outset(elevation() * tx, elevation() * ty); + set_paint_bounds(bounds); } -#endif // defined(OS_FUCHSIA) - 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); + // The compositor will paint this layer (which is a solid color) via the + // color on |SceneUpdateContext::Frame|. + // + // The child layers will be painted into the texture used by the Frame, so + // painting them here would actually cause them to be painted on the display + // twice -- once into the current canvas (which may be inside of another + // Frame) and once into the Frame's canvas (which is then stacked on top of + // the current canvas). + if (PhysicalShapeLayerBase::should_system_composite() && needs_system_composite()) { + PhysicalShapeLayerBase::Paint(context); + return; + } + + 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); @@ -181,7 +159,7 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { context.leaf_nodes_canvas->drawPaint(paint); } - PaintChildren(context); + PhysicalShapeLayerBase::Paint(context); context.internal_nodes_canvas->restoreToCount(saveCount); } diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index 50a63bc62cc59..d327c83d8eac0 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -9,15 +9,26 @@ namespace flutter { -class PhysicalShapeLayer : public ContainerLayer { +#if defined(OS_FUCHSIA) +using PhysicalShapeLayerBase = FuchsiaSystemCompositedContainerLayer; +#else +class PhysicalShapeLayerBase : public ElevatedContainerLayer { public: - PhysicalShapeLayer(SkColor color, - SkColor shadow_color, - float elevation, - const SkPath& path, - Clip clip_behavior); - ~PhysicalShapeLayer() override; + static bool should_system_composite() { return false; } + + PhysicalShapeLayerBase(SkColor color, float elevation) + : ElevatedContainerLayer(elevation), + color_(color) {} + + SkColor color() const { return color_; } + + private: + SkColor color_; +}; +#endif +class PhysicalShapeLayer : public PhysicalShapeLayerBase { + public: static void DrawShadow(SkCanvas* canvas, const SkPath& path, SkColor color, @@ -25,25 +36,20 @@ class PhysicalShapeLayer : public ContainerLayer { bool transparentOccluder, SkScalar dpr); - void Preroll(PrerollContext* context, const SkMatrix& matrix) override; + PhysicalShapeLayer(SkColor color, + SkColor shadow_color, + float elevation, + const SkPath& path, + Clip clip_behavior); + ~PhysicalShapeLayer() override = default; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; -#if defined(OS_FUCHSIA) - void UpdateScene(SceneUpdateContext& context) override; -#endif // defined(OS_FUCHSIA) - private: - SkColor color_; SkColor shadow_color_; - float elevation_ = 0.0f; - float total_elevation_ = 0.0f; SkPath path_; - bool isRect_; - SkRRect frameRRect_; Clip clip_behavior_; - - friend class PhysicalShapeLayer_TotalElevation_Test; }; } // namespace flutter diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index 4bb13ad7bc877..241b701e4e475 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -38,7 +38,7 @@ TEST(PhysicalShapeLayer, TotalElevation) { unused_stopwatch, // engine time (dont care) unused_texture_registry, // texture registry (not supported) false, // checkerboard_offscreen_layers - 1.0f, // physical depth + 6.0f, // physical depth 1.0f, // device pixel ratio 0.0f, // total elevation }; @@ -55,14 +55,14 @@ TEST(PhysicalShapeLayer, TotalElevation) { // | \ // | layers[2] +3.0f // | | - // | layers[3] +4.0f + // | layers[3] +4.0f (clamped to 6.0f) // | // | // layers[1] + 2.0f - EXPECT_EQ(layers[0]->total_elevation_, 1.0f); - EXPECT_EQ(layers[1]->total_elevation_, 3.0f); - EXPECT_EQ(layers[2]->total_elevation_, 4.0f); - EXPECT_EQ(layers[3]->total_elevation_, 8.0f); + EXPECT_EQ(layers[0]->total_elevation(), 1.0f); + EXPECT_EQ(layers[1]->total_elevation(), 3.0f); + EXPECT_EQ(layers[2]->total_elevation(), 4.0f); + EXPECT_EQ(layers[3]->total_elevation(), 6.0f); } } // namespace flutter diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index 01f73d2a09b2d..ccbe183cef7aa 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -294,29 +294,17 @@ SceneUpdateContext::Shape::Shape(SceneUpdateContext& context) SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, - float local_elevation, - float world_elevation, + float elevation, Layer* layer) : Shape(context), rrect_(rrect), color_(color), 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); - } + entity_node().SetTranslation(0.f, 0.f, -elevation); + SetEntityNodeClipPlanes(entity_node(), rrect_.getBounds()); + + entity_node().AddChild(shape_node()); } SceneUpdateContext::Frame::~Frame() { diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index a9b4f73bf78bc..bcaf2ef40ba49 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -115,8 +115,7 @@ class SceneUpdateContext { Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, - float local_elevation = 0.0f, - float parent_elevation = 0.0f, + float elevation = 0.0f, Layer* layer = nullptr); virtual ~Frame(); From eb94faa56ada181a352e9da25e08bd876ae12602 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 11 Nov 2019 11:02:34 -0800 Subject: [PATCH 06/11] Wire up OpacityLayer to Scenic --- flow/layers/child_scene_layer.cc | 17 +++++- flow/layers/container_layer.cc | 28 ++++++--- flow/layers/container_layer.h | 4 +- flow/layers/layer.h | 5 +- flow/layers/layer_tree.cc | 2 +- flow/layers/opacity_layer.cc | 82 ++++++++++++++++++++++----- flow/layers/opacity_layer.h | 36 +++++++++--- flow/layers/physical_shape_layer.cc | 55 ++++++++++-------- flow/layers/physical_shape_layer.h | 4 +- flow/scene_update_context.cc | 88 ++++++++++++++--------------- flow/scene_update_context.h | 38 ++++++------- 11 files changed, 236 insertions(+), 123 deletions(-) diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index f4100be2fee69..66873e360f70c 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -19,10 +19,25 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id, void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { 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()); + + // 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/container_layer.cc b/flow/layers/container_layer.cc index 3ee7356470e8b..697b490c4c543 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -125,9 +125,10 @@ void ElevatedContainerLayer::Preroll(PrerollContext* context, const SkMatrix& ma context->total_elevation = parent_elevation_; } -FuchsiaSystemCompositedContainerLayer::FuchsiaSystemCompositedContainerLayer(SkColor color, float elevation) +FuchsiaSystemCompositedContainerLayer::FuchsiaSystemCompositedContainerLayer(SkColor color, SkAlpha opacity, float elevation) : ElevatedContainerLayer(elevation), - color_(color) {} + color_(color), + opacity_(opacity) {} void FuchsiaSystemCompositedContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "SystemCompositedContainerLayer::Preroll"); @@ -138,18 +139,31 @@ void FuchsiaSystemCompositedContainerLayer::Preroll(PrerollContext* context, con // System-composite this layer. set_needs_system_composite(true); + const float parent_is_opaque = context->is_opaque; + context->mutators_stack.PushOpacity(opacity_); + context->is_opaque = parent_is_opaque && (opacity_ == 255); ElevatedContainerLayer::Preroll(context, matrix); + context->is_opaque = parent_is_opaque; + context->mutators_stack.Pop(); } void FuchsiaSystemCompositedContainerLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "SystemCompositedContainerLayer::Paint"); + FML_DCHECK(needs_painting()); + + if (needs_system_composite()) { #if !defined(OS_FUCHSIA) - FML_NOTIMPLEMENTED(); + FML_NOTIMPLEMENTED(); #endif // !defined(OS_FUCHSIA) - // TODO: hole punch - // If this is actually called, it's because flow is attempting to paint this - // layer onto the frame behind it which gives us a chance to hole-punch + // 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); + } } #if defined(OS_FUCHSIA) @@ -170,7 +184,7 @@ void FuchsiaSystemCompositedContainerLayer::UpdateScene(SceneUpdateContext& cont } SceneUpdateContext::Frame frame(context, rrect_, color_, - elevation(), this); + opacity_ / 255.0f, elevation(), this); // Paint the child layers into the Frame. for (auto& layer : layers()) { if (layer->needs_painting()) { diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index 91d730dc57604..8d1721053b77f 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -68,7 +68,7 @@ class FuchsiaSystemCompositedContainerLayer : public ElevatedContainerLayer { public: static bool should_system_composite() { return true; } - FuchsiaSystemCompositedContainerLayer(SkColor color, float elevation); + FuchsiaSystemCompositedContainerLayer(SkColor color, SkAlpha opacity, float elevation); ~FuchsiaSystemCompositedContainerLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; @@ -82,10 +82,12 @@ class FuchsiaSystemCompositedContainerLayer : public ElevatedContainerLayer { } SkColor color() const { return color_; } + SkAlpha opacity() const { return opacity_; } private: SkRRect rrect_ = SkRRect::MakeEmpty(); SkColor color_ = SK_ColorTRANSPARENT; + SkAlpha opacity_ = 255; FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaSystemCompositedContainerLayer); }; diff --git a/flow/layers/layer.h b/flow/layers/layer.h index a9c4a3aa818ce..731509876b611 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -60,10 +60,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 77d6fb01d765e..d9e2a3859c6f8 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -75,7 +75,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, context, SkRRect::MakeRect( SkRect::MakeWH(frame_size_.width(), frame_size_.height())), - SK_ColorTRANSPARENT, /* elevation */ 0.0f); + SK_ColorTRANSPARENT, /* opacity */ 1.0f, /* elevation */ 0.0f); 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 dc24a6a541ca4..ef41cadb1ebaa 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -9,8 +9,24 @@ namespace flutter { -OpacityLayer::OpacityLayer(int alpha, const SkPoint& offset) - : alpha_(alpha), offset_(offset) { +constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.001f; + +#if !defined(OS_FUCHSIA) +void OpacityLayerBase::Preroll(PrerollContext* context, const SkMatrix& matrix) { + const SkAlpha alpha = SkColorGetA(color()); + const float parent_is_opaque = context->is_opaque; + + context->mutators_stack.PushOpacity(alpha); + context->is_opaque = parent_is_opaque && (alpha == 255); + ContainerLayer::Preroll(context, matrix); + context->is_opaque = parent_is_opaque; + context->mutators_stack.Pop(); +} +#endif + +OpacityLayer::OpacityLayer(SkAlpha opacity, const SkPoint& offset) + : OpacityLayerBase(SK_ColorBLACK, opacity, kOpacityElevationWhenUsingSystemCompositor), + offset_(offset) { // Ensure OpacityLayer has only one direct child. // // This is needed to ensure that retained rendering can always be applied to @@ -31,32 +47,72 @@ 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_); - ContainerLayer::Preroll(context, child_matrix); - context->mutators_stack.Pop(); + OpacityLayerBase::Preroll(context, child_matrix); 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; + // When using the system compositor, do not include the offset or use the + // raster cache, since we are rendering as a separate piece of geometry. + if (OpacityLayerBase::should_system_composite()) { + set_needs_system_composite(true); + set_dimensions(SkRRect::MakeRect(paint_bounds())); + + // If the frame behind us is opaque, don't punch a hole in it for group + // opacity. + if (context->is_opaque) { + set_paint_bounds(SkRect::MakeEmpty()); + } + } 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; #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()); + // The compositor will paint this layer (which is |Sk_ColorBLACK| with alpha + // scaled by opacity) via the model color on |SceneUpdateContext::Frame|. + // + // The child layers will be painted into the texture used by the Frame, so + // painting them here would actually cause them to be painted on the display + // twice -- once into the current canvas (which may be inside of another + // Frame) and once into the Frame's texture (which is then drawn on top of the + // current canvas). + if (OpacityLayerBase::should_system_composite()) { + FML_DCHECK(needs_system_composite()); + + OpacityLayerBase::Paint(context); + return; + } + SkPaint paint; - paint.setAlpha(alpha_); + paint.setAlpha(opacity()); SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->translate(offset_.fX, offset_.fY); @@ -92,7 +148,7 @@ void OpacityLayer::Paint(PaintContext& context) const { Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint); - PaintChildren(context); + OpacityLayerBase::Paint(context); } ContainerLayer* OpacityLayer::GetChildContainer() const { diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index c8ecad959bb82..d9a056789e715 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -9,11 +9,35 @@ namespace flutter { +#if defined(OS_FUCHSIA) +using OpacityLayerBase = FuchsiaSystemCompositedContainerLayer; +#else +class OpacityLayerBase : public ContainerLayer { + public: + static bool should_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_; +}; +#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, the // |EnsureSingleChild| will assert if there are no children. -class OpacityLayer : public ContainerLayer { +class OpacityLayer : public OpacityLayerBase { public: // An offset is provided here because OpacityLayer.addToScene method in the // Flutter framework can take an optional offset argument. @@ -25,22 +49,20 @@ 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); ~OpacityLayer() override; 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 5e27eb6b8e1c4..45e97b4d62d39 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -17,35 +17,35 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, float elevation, const SkPath& path, Clip clip_behavior) - : PhysicalShapeLayerBase(color, elevation), + : PhysicalShapeLayerBase(color, elevation, SK_AlphaOPAQUE), shadow_color_(shadow_color), path_(path), clip_behavior_(clip_behavior) { // If rendering as a separate frame using the system compositor, then make // sure to set up the properties needed to do so. -#if defined(OS_FUCHSIA) - SkRect rect; - SkRRect rrect; - if (path.isRect(&rect)) { - rrect = SkRRect::MakeRect(rect); - } else if (path.isRRect(&rrect)) { - // Nothing needed here, as isRRect will fill in frameRRect_ already. - } else if (path.isOval(&rect)) { - // isRRect returns false for ovals, so we need to explicitly check isOval - // as well. - rrect = SkRRect::MakeOval(rect); - } else { - // Scenic currently doesn't provide an easy way to create shapes from - // arbitrary paths. - // For shapes that cannot be represented as a rounded rectangle we - // default to use the bounding rectangle. - // TODO(amirh): fix this once we have a way to create a Scenic shape from - // an SkPath. - rrect = SkRRect::MakeRect(path.getBounds()); + if (PhysicalShapeLayerBase::should_system_composite()) { + SkRect rect; + SkRRect rrect; + if (path.isRect(&rect)) { + rrect = SkRRect::MakeRect(rect); + } else if (path.isRRect(&rrect)) { + // Nothing needed here, as isRRect will fill in frameRRect_ already. + } else if (path.isOval(&rect)) { + // isRRect returns false for ovals, so we need to explicitly check isOval + // as well. + rrect = SkRRect::MakeOval(rect); + } else { + // Scenic currently doesn't provide an easy way to create shapes from + // arbitrary paths. + // For shapes that cannot be represented as a rounded rectangle we + // default to use the bounding rectangle. + // TODO(amirh): fix this once we have a way to create a Scenic shape from + // an SkPath. + rrect = SkRRect::MakeRect(path.getBounds()); + } + + set_dimensions(rrect); } - - set_dimensions(rrect); -#endif } void PhysicalShapeLayer::Preroll(PrerollContext* context, @@ -61,6 +61,11 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context, // The system compositor can handle shadows if it is being used. if (PhysicalShapeLayerBase::should_system_composite()) { + // If the frame behind us is opaque, don't punch a hole in it for group + // opacity. + if (context->is_opaque) { + set_paint_bounds(SkRect::MakeEmpty()); + } return; } @@ -117,7 +122,9 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { // twice -- once into the current canvas (which may be inside of another // Frame) and once into the Frame's canvas (which is then stacked on top of // the current canvas). - if (PhysicalShapeLayerBase::should_system_composite() && needs_system_composite()) { + if (PhysicalShapeLayerBase::should_system_composite()) { + FML_DCHECK(needs_system_composite()); + PhysicalShapeLayerBase::Paint(context); return; } diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index d327c83d8eac0..7d23725dcb869 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -16,10 +16,12 @@ class PhysicalShapeLayerBase : public ElevatedContainerLayer { public: static bool should_system_composite() { return false; } - PhysicalShapeLayerBase(SkColor color, float elevation) + PhysicalShapeLayerBase(SkColor color, SkAlpha opacity, float elevation) : ElevatedContainerLayer(elevation), color_(color) {} + void set_dimensions(SkRRect rrect) {} + SkColor color() const { return color_; } private: diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index ccbe183cef7aa..0e694b8e6e548 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 { @@ -59,14 +60,10 @@ 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; @@ -95,7 +92,9 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, // Check whether a solid color will suffice. if (paint_layers.empty()) { - SetShapeColor(shape_node, color); + scenic::Material material(session_); + SetMaterialColor(material, color, opacity); + shape_node.SetMaterial(material); return; } @@ -103,43 +102,38 @@ 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, paint_bounds, std::move(paint_layers), layer, + color, scale_x, scale_y, shape_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; } - SetShapeColor(shape_node, color); -} + // No texture was needed, so apply a solid color to the whole shape. + if (SkColorGetA(color) != 0 && opacity != 0.0f) { + scenic::Material material(session_); -void SceneUpdateContext::SetShapeColor(scenic::ShapeNode& shape_node, - SkColor color) { - if (SkColorGetA(color) == 0) + SetMaterialColor(material, color, opacity); + shape_node.SetMaterial(material); return; + } +} - scenic::Material material(session_); +void SceneUpdateContext::SetMaterialColor(scenic::Material& material, + SkColor color, + float opacity) { + const SkAlpha color_alpha = (SkAlpha)(SkColorGetA(color) * opacity); material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), - SkColorGetA(color)); - shape_node.SetMaterial(material); + color_alpha); } scenic::Image* SceneUpdateContext::GenerateImageIfNeeded( @@ -228,6 +222,7 @@ SceneUpdateContext::Entity::Entity(SceneUpdateContext& context) entity_node_(context.session()) { if (previous_entity_) previous_entity_->embedder_node().AddChild(entity_node_); + context.top_entity_ = this; } @@ -286,31 +281,38 @@ 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::Clip::Clip(SceneUpdateContext& context, + const SkRect& shape_bounds) + : Entity(context) { + SetEntityNodeClipPlanes(entity_node(), shape_bounds); } SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, + float opacity, float elevation, Layer* layer) - : Shape(context), + : Entity(context), + opacity_node_(context.session()), + shape_node_(context.session()), + layer_(layer), rrect_(rrect), - color_(color), paint_bounds_(SkRect::MakeEmpty()), - layer_(layer) { + color_(color), + opacity_(opacity) { entity_node().SetTranslation(0.f, 0.f, -elevation); SetEntityNodeClipPlanes(entity_node(), rrect_.getBounds()); - entity_node().AddChild(shape_node()); + entity_node().AddChild(opacity_node_); + entity_node().AddChild(shape_node_); + opacity_node_.SetOpacity(opacity_); } SceneUpdateContext::Frame::~Frame() { - context().CreateFrame(std::move(entity_node()), std::move(shape_node()), - rrect_, color_, paint_bounds_, std::move(paint_layers_), - layer_); + context().CreateFrame(std::move(entity_node()), std::move(shape_node_), + rrect_, color_, opacity_, paint_bounds_, + std::move(paint_layers_), layer_); } void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { @@ -319,10 +321,4 @@ 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 bcaf2ef40ba49..dfc945e48a04c 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -89,25 +89,20 @@ class SceneUpdateContext { float scale_x, float scale_y, float scale_z); - virtual ~Transform(); + ~Transform() override; private: float const previous_scale_x_; float const previous_scale_y_; }; - class Shape : public Entity { + class Clip : public Entity { public: - Shape(SceneUpdateContext& context); - virtual ~Shape() = default; - - scenic::ShapeNode& shape_node() { return shape_node_; } - - private: - scenic::ShapeNode shape_node_; + Clip(SceneUpdateContext& context, const SkRect& shape_bounds); + ~Clip() override = default; }; - 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,25 +110,25 @@ class SceneUpdateContext { Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, + float opacity = 1.0f, float elevation = 0.0f, Layer* layer = nullptr); - virtual ~Frame(); + ~Frame() override; + scenic::ContainerNode& embedder_node() override { return opacity_node_; } void AddPaintLayer(Layer* layer); private: - const SkRRect& rrect_; - SkColor const color_; + scenic::OpacityNodeHACK opacity_node_; + scenic::ShapeNode shape_node_; std::vector paint_layers_; - SkRect paint_bounds_; Layer* layer_; - }; - class Clip : public Entity { - public: - Clip(SceneUpdateContext& context, const SkRect& shape_bounds); - ~Clip() = default; + SkRRect rrect_; + SkRect paint_bounds_; + SkColor color_; + float opacity_; }; SceneUpdateContext(scenic::Session* session, @@ -206,6 +201,7 @@ class SceneUpdateContext { scenic::ShapeNode shape_node, const SkRRect& rrect, SkColor color, + float opacity, const SkRect& paint_bounds, std::vector paint_layers, Layer* layer); @@ -217,7 +213,9 @@ class SceneUpdateContext { std::vector paint_layers, Layer* layer, scenic::EntityNode entity_node); - void SetShapeColor(scenic::ShapeNode& shape_node, SkColor color); + void SetMaterialColor(scenic::Material& material, + SkColor color, + float opacity); scenic::Image* GenerateImageIfNeeded(SkColor color, SkScalar scale_x, SkScalar scale_y, From 89c7b837f3f74a0b4bedfd0445e861e60f27dd5e Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 11 Nov 2019 11:06:53 -0800 Subject: [PATCH 07/11] Move FUCHSIA_OS to cc; cleanup declarations --- flow/layers/backdrop_filter_layer.cc | 6 +-- flow/layers/backdrop_filter_layer.h | 2 +- flow/layers/child_scene_layer.cc | 1 + flow/layers/child_scene_layer.h | 4 +- flow/layers/clip_path_layer.cc | 21 +++++---- flow/layers/clip_path_layer.h | 6 +-- flow/layers/clip_rect_layer.cc | 26 ++++++----- flow/layers/clip_rect_layer.h | 5 +-- flow/layers/clip_rrect_layer.cc | 21 +++++---- flow/layers/clip_rrect_layer.h | 6 +-- flow/layers/color_filter_layer.cc | 6 +-- flow/layers/color_filter_layer.h | 2 +- flow/layers/container_layer.cc | 34 +++++--------- flow/layers/container_layer.h | 21 +++------ flow/layers/layer.cc | 20 +++------ flow/layers/layer.h | 54 ++++++++++------------ flow/layers/layer_tree.cc | 4 ++ flow/layers/layer_tree.h | 4 ++ flow/layers/opacity_layer.cc | 6 ++- flow/layers/opacity_layer.h | 4 +- flow/layers/performance_overlay_layer.cc | 4 +- flow/layers/performance_overlay_layer.h | 2 + flow/layers/physical_shape_layer.cc | 5 +++ flow/layers/physical_shape_layer.h | 1 + flow/layers/picture_layer.cc | 4 +- flow/layers/picture_layer.h | 10 ++--- flow/layers/platform_view_layer.cc | 2 - flow/layers/platform_view_layer.h | 2 +- flow/layers/shader_mask_layer.cc | 6 +-- flow/layers/shader_mask_layer.h | 3 +- flow/layers/texture_layer.cc | 2 - flow/layers/texture_layer.h | 2 +- flow/layers/transform_layer.cc | 19 ++++---- flow/layers/transform_layer.h | 7 ++- flow/raster_cache.cc | 7 +-- flow/raster_cache.h | 8 ++-- flow/scene_update_context.h | 1 + lib/ui/compositing/scene_builder.cc | 57 +++++++++++++----------- lib/ui/compositing/scene_builder.h | 30 +++++-------- lib/ui/painting/engine_layer.cc | 19 ++++---- lib/ui/painting/engine_layer.h | 17 +++---- 41 files changed, 219 insertions(+), 242 deletions(-) diff --git a/flow/layers/backdrop_filter_layer.cc b/flow/layers/backdrop_filter_layer.cc index 573db97f191a2..2195ffb4f47fb 100644 --- a/flow/layers/backdrop_filter_layer.cc +++ b/flow/layers/backdrop_filter_layer.cc @@ -4,13 +4,13 @@ #include "flutter/flow/layers/backdrop_filter_layer.h" +#include "flutter/fml/trace_event.h" + namespace flutter { BackdropFilterLayer::BackdropFilterLayer(sk_sp filter) : filter_(std::move(filter)) {} -BackdropFilterLayer::~BackdropFilterLayer() = default; - void BackdropFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "BackdropFilterLayer::Paint"); FML_DCHECK(needs_painting()); @@ -18,7 +18,7 @@ void BackdropFilterLayer::Paint(PaintContext& context) const { Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create( context, SkCanvas::SaveLayerRec{&paint_bounds(), nullptr, filter_.get(), 0}); - PaintChildren(context); + ContainerLayer::Paint(context); } } // namespace flutter diff --git a/flow/layers/backdrop_filter_layer.h b/flow/layers/backdrop_filter_layer.h index ede9ceeef41f8..0f4fd3613a6a1 100644 --- a/flow/layers/backdrop_filter_layer.h +++ b/flow/layers/backdrop_filter_layer.h @@ -14,7 +14,7 @@ namespace flutter { class BackdropFilterLayer : public ContainerLayer { public: BackdropFilterLayer(sk_sp filter); - ~BackdropFilterLayer() override; + ~BackdropFilterLayer() override = default; void Paint(PaintContext& context) const override; diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 66873e360f70c..637346789b037 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -5,6 +5,7 @@ #include "flutter/flow/layers/child_scene_layer.h" #include "flutter/flow/view_holder.h" +#include "flutter/fml/trace_event.h" namespace flutter { diff --git a/flow/layers/child_scene_layer.h b/flow/layers/child_scene_layer.h index b5e26315899e5..43aea8093218d 100644 --- a/flow/layers/child_scene_layer.h +++ b/flow/layers/child_scene_layer.h @@ -24,10 +24,8 @@ class ChildSceneLayer : public Layer { ~ChildSceneLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - - void Paint(PaintContext& context) const override; - void UpdateScene(SceneUpdateContext& context) override; + void Paint(PaintContext& context) const override; private: zx_koid_t layer_id_ = ZX_KOID_INVALID; diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index d08c19b34eeb9..0db4f6ca4aab4 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -4,10 +4,10 @@ #include "flutter/flow/layers/clip_path_layer.h" -#if defined(OS_FUCHSIA) - -#include "lib/ui/scenic/cpp/commands.h" +#include "flutter/fml/trace_event.h" +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck #endif // defined(OS_FUCHSIA) namespace flutter { @@ -17,18 +17,17 @@ ClipPathLayer::ClipPathLayer(const SkPath& clip_path, Clip clip_behavior) FML_DCHECK(clip_behavior != Clip::none); } -ClipPathLayer::~ClipPathLayer() = default; - void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkRect previous_cull_rect = context->cull_rect; SkRect clip_path_bounds = clip_path_.getBounds(); if (context->cull_rect.intersect(clip_path_bounds)) { context->mutators_stack.PushClipPath(clip_path_); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); + ContainerLayer::Preroll(context, matrix); - if (child_paint_bounds.intersect(clip_path_bounds)) { - set_paint_bounds(child_paint_bounds); + if (clip_path_bounds.intersect(paint_bounds())) { + set_paint_bounds(clip_path_bounds); + } else { + set_paint_bounds(SkRect::MakeEmpty()); } context->mutators_stack.Pop(); } @@ -42,7 +41,7 @@ void ClipPathLayer::UpdateScene(SceneUpdateContext& context) { // TODO(liyuqian): respect clip_behavior_ SceneUpdateContext::Clip clip(context, clip_path_.getBounds()); - UpdateSceneChildren(context); + ContainerLayer::UpdateScene(context); } #endif // defined(OS_FUCHSIA) @@ -58,7 +57,7 @@ void ClipPathLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); } - PaintChildren(context); + ContainerLayer::Paint(context); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } diff --git a/flow/layers/clip_path_layer.h b/flow/layers/clip_path_layer.h index fd4d56f0db7f0..db435a388a2b1 100644 --- a/flow/layers/clip_path_layer.h +++ b/flow/layers/clip_path_layer.h @@ -12,15 +12,13 @@ namespace flutter { class ClipPathLayer : public ContainerLayer { public: ClipPathLayer(const SkPath& clip_path, Clip clip_behavior = Clip::antiAlias); - ~ClipPathLayer() override; + ~ClipPathLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - - void Paint(PaintContext& context) const override; - #if defined(OS_FUCHSIA) void UpdateScene(SceneUpdateContext& context) override; #endif // defined(OS_FUCHSIA) + void Paint(PaintContext& context) const override; private: SkPath clip_path_; diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index de7590624e408..9bccc9e2d870f 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -4,6 +4,12 @@ #include "flutter/flow/layers/clip_rect_layer.h" +#include "flutter/fml/trace_event.h" + +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { ClipRectLayer::ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior) @@ -11,17 +17,17 @@ ClipRectLayer::ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior) FML_DCHECK(clip_behavior != Clip::none); } -ClipRectLayer::~ClipRectLayer() = default; - void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkRect previous_cull_rect = context->cull_rect; - if (context->cull_rect.intersect(clip_rect_)) { - context->mutators_stack.PushClipRect(clip_rect_); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); + SkRect clip_rect_bounds = clip_rect_; + if (context->cull_rect.intersect(clip_rect_bounds)) { + context->mutators_stack.PushClipRect(clip_rect_bounds); + ContainerLayer::Preroll(context, matrix); - if (child_paint_bounds.intersect(clip_rect_)) { - set_paint_bounds(child_paint_bounds); + if (clip_rect_bounds.intersect(paint_bounds())) { + set_paint_bounds(clip_rect_bounds); + } else { + set_paint_bounds(SkRect::MakeEmpty()); } context->mutators_stack.Pop(); } @@ -35,7 +41,7 @@ void ClipRectLayer::UpdateScene(SceneUpdateContext& context) { // TODO(liyuqian): respect clip_behavior_ SceneUpdateContext::Clip clip(context, clip_rect_); - UpdateSceneChildren(context); + ContainerLayer::UpdateScene(context); } #endif // defined(OS_FUCHSIA) @@ -51,7 +57,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); } - PaintChildren(context); + ContainerLayer::Paint(context); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } diff --git a/flow/layers/clip_rect_layer.h b/flow/layers/clip_rect_layer.h index 76c5a3f01c873..f661af86db94d 100644 --- a/flow/layers/clip_rect_layer.h +++ b/flow/layers/clip_rect_layer.h @@ -12,14 +12,13 @@ namespace flutter { class ClipRectLayer : public ContainerLayer { public: ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior); - ~ClipRectLayer() override; + ~ClipRectLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - void Paint(PaintContext& context) const override; - #if defined(OS_FUCHSIA) void UpdateScene(SceneUpdateContext& context) override; #endif // defined(OS_FUCHSIA) + void Paint(PaintContext& context) const override; private: SkRect clip_rect_; diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 9899a1658732d..a2901b5d1034d 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -4,6 +4,12 @@ #include "flutter/flow/layers/clip_rrect_layer.h" +#include "flutter/fml/trace_event.h" + +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { ClipRRectLayer::ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior) @@ -11,18 +17,17 @@ ClipRRectLayer::ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior) FML_DCHECK(clip_behavior != Clip::none); } -ClipRRectLayer::~ClipRRectLayer() = default; - void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkRect previous_cull_rect = context->cull_rect; SkRect clip_rrect_bounds = clip_rrect_.getBounds(); if (context->cull_rect.intersect(clip_rrect_bounds)) { context->mutators_stack.PushClipRRect(clip_rrect_); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); + ContainerLayer::Preroll(context, matrix); - if (child_paint_bounds.intersect(clip_rrect_bounds)) { - set_paint_bounds(child_paint_bounds); + if (clip_rrect_bounds.intersect(paint_bounds())) { + set_paint_bounds(clip_rrect_bounds); + } else { + set_paint_bounds(SkRect::MakeEmpty()); } context->mutators_stack.Pop(); } @@ -36,7 +41,7 @@ void ClipRRectLayer::UpdateScene(SceneUpdateContext& context) { // TODO(liyuqian): respect clip_behavior_ SceneUpdateContext::Clip clip(context, clip_rrect_.getBounds()); - UpdateSceneChildren(context); + ContainerLayer::UpdateScene(context); } #endif // defined(OS_FUCHSIA) @@ -52,7 +57,7 @@ void ClipRRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); } - PaintChildren(context); + ContainerLayer::Paint(context); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } diff --git a/flow/layers/clip_rrect_layer.h b/flow/layers/clip_rrect_layer.h index 53f74f30a0776..af2492216c3ef 100644 --- a/flow/layers/clip_rrect_layer.h +++ b/flow/layers/clip_rrect_layer.h @@ -12,15 +12,13 @@ namespace flutter { class ClipRRectLayer : public ContainerLayer { public: ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior); - ~ClipRRectLayer() override; + ~ClipRRectLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - - void Paint(PaintContext& context) const override; - #if defined(OS_FUCHSIA) void UpdateScene(SceneUpdateContext& context) override; #endif // defined(OS_FUCHSIA) + void Paint(PaintContext& context) const override; private: SkRRect clip_rrect_; diff --git a/flow/layers/color_filter_layer.cc b/flow/layers/color_filter_layer.cc index f838b0612b2e5..755c2fe3450be 100644 --- a/flow/layers/color_filter_layer.cc +++ b/flow/layers/color_filter_layer.cc @@ -4,13 +4,13 @@ #include "flutter/flow/layers/color_filter_layer.h" +#include "flutter/fml/trace_event.h" + namespace flutter { ColorFilterLayer::ColorFilterLayer(sk_sp filter) : filter_(std::move(filter)) {} -ColorFilterLayer::~ColorFilterLayer() = default; - void ColorFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ColorFilterLayer::Paint"); FML_DCHECK(needs_painting()); @@ -20,7 +20,7 @@ void ColorFilterLayer::Paint(PaintContext& context) const { Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create(context, paint_bounds(), &paint); - PaintChildren(context); + ContainerLayer::Paint(context); } } // namespace flutter diff --git a/flow/layers/color_filter_layer.h b/flow/layers/color_filter_layer.h index cf1de4cb610fc..3e8bef039a04c 100644 --- a/flow/layers/color_filter_layer.h +++ b/flow/layers/color_filter_layer.h @@ -14,7 +14,7 @@ namespace flutter { class ColorFilterLayer : public ContainerLayer { public: ColorFilterLayer(sk_sp filter); - ~ColorFilterLayer() override; + ~ColorFilterLayer() override = default; void Paint(PaintContext& context) const override; diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index 697b490c4c543..faa4b597ecd1c 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -4,6 +4,12 @@ #include "flutter/flow/layers/container_layer.h" +#include "flutter/fml/trace_event.h" + +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { namespace { @@ -26,10 +32,6 @@ float ClampElevation(float elevation, } // namespace -ContainerLayer::ContainerLayer() {} - -ContainerLayer::~ContainerLayer() = default; - void ContainerLayer::Add(std::shared_ptr layer) { layers_.emplace_back(std::move(layer)); } @@ -37,17 +39,11 @@ void ContainerLayer::Add(std::shared_ptr layer) { void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "ContainerLayer::Preroll"); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); - set_paint_bounds(child_paint_bounds); -} - -void ContainerLayer::PrerollChildren(PrerollContext* context, - const SkMatrix& child_matrix, - SkRect* child_paint_bounds) { // Platform views have no children, so context->has_platform_view should // always be false. FML_DCHECK(!context->has_platform_view); + + SkRect child_paint_bounds = SkRect::MakeEmpty(); bool child_has_platform_view = false; for (auto& layer : layers_) { // Reset context->has_platform_view to false so that layers aren't treated @@ -55,25 +51,21 @@ void ContainerLayer::PrerollChildren(PrerollContext* context, // sibling tree. context->has_platform_view = false; - layer->Preroll(context, child_matrix); - + layer->Preroll(context, matrix); if (layer->needs_system_composite()) { set_needs_system_composite(true); } - child_paint_bounds->join(layer->paint_bounds()); + child_paint_bounds.join(layer->paint_bounds()); child_has_platform_view = child_has_platform_view || context->has_platform_view; } context->has_platform_view = child_has_platform_view; + set_paint_bounds(child_paint_bounds); } void ContainerLayer::Paint(PaintContext& context) const { - PaintChildren(context); -} - -void ContainerLayer::PaintChildren(PaintContext& context) const { FML_DCHECK(needs_painting()); // Intentionally not tracing here as there should be no self-time @@ -88,10 +80,6 @@ void ContainerLayer::PaintChildren(PaintContext& context) const { #if defined(OS_FUCHSIA) void ContainerLayer::UpdateScene(SceneUpdateContext& context) { - UpdateSceneChildren(context); -} - -void ContainerLayer::UpdateSceneChildren(SceneUpdateContext& context) { FML_DCHECK(needs_system_composite()); // Update all of the Layers which are part of the container. This may cause diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index 8d1721053b77f..a7456e00fa1c8 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -5,15 +5,19 @@ #ifndef FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_ #define FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_ +#include #include + #include "flutter/flow/layers/layer.h" +#include "third_party/skia/include/core/SkMatrix.h" +#include "third_party/skia/include/core/SkRect.h" namespace flutter { class ContainerLayer : public Layer { public: - ContainerLayer(); - ~ContainerLayer() override; + ContainerLayer() = default; + ~ContainerLayer() override = default; virtual void Add(std::shared_ptr layer); @@ -25,19 +29,6 @@ class ContainerLayer : public Layer { const std::vector>& layers() const { return layers_; } - protected: - void PrerollChildren(PrerollContext* context, - const SkMatrix& child_matrix, - SkRect* child_paint_bounds); - void PaintChildren(PaintContext& context) const; - -#if defined(OS_FUCHSIA) - void UpdateSceneChildren(SceneUpdateContext& context); -#endif // defined(OS_FUCHSIA) - - // For OpacityLayer to restructure to have a single child. - void ClearChildren() { layers_.clear(); } - private: std::vector> layers_; diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index 5ad6a6bee1499..3933ef2a2953b 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -5,18 +5,11 @@ #include "flutter/flow/layers/layer.h" #include "flutter/flow/paint_utils.h" -#include "third_party/skia/include/core/SkColorFilter.h" namespace flutter { +namespace { -Layer::Layer() - : paint_bounds_(SkRect::MakeEmpty()), - unique_id_(NextUniqueID()), - needs_system_composite_(false) {} - -Layer::~Layer() = default; - -uint64_t Layer::NextUniqueID() { +uint64_t NextUniqueID() { static std::atomic nextID(1); uint64_t id; do { @@ -25,11 +18,12 @@ uint64_t Layer::NextUniqueID() { return id; } -void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {} +} // namespace -#if defined(OS_FUCHSIA) -void Layer::UpdateScene(SceneUpdateContext& context) {} -#endif // defined(OS_FUCHSIA) +Layer::Layer() + : paint_bounds_(SkRect::MakeEmpty()), + unique_id_(NextUniqueID()), + needs_system_composite_(false) {} Layer::AutoSaveLayer::AutoSaveLayer(const PaintContext& paint_context, const SkRect& bounds, diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 731509876b611..2153d2737f827 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -5,38 +5,22 @@ #ifndef FLUTTER_FLOW_LAYERS_LAYER_H_ #define FLUTTER_FLOW_LAYERS_LAYER_H_ -#include -#include - #include "flutter/flow/embedded_views.h" #include "flutter/flow/instrumentation.h" #include "flutter/flow/raster_cache.h" #include "flutter/flow/texture.h" #include "flutter/fml/build_config.h" #include "flutter/fml/compiler_specific.h" -#include "flutter/fml/logging.h" #include "flutter/fml/macros.h" -#include "flutter/fml/trace_event.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkMatrix.h" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkPicture.h" -#include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/utils/SkNWayCanvas.h" - -#if defined(OS_FUCHSIA) - -#include "flutter/flow/scene_update_context.h" //nogncheck -#include "lib/ui/scenic/cpp/resources.h" //nogncheck -#include "lib/ui/scenic/cpp/session.h" //nogncheck - -#endif // defined(OS_FUCHSIA) namespace flutter { +class SceneUpdateContext; + static constexpr SkRect kGiantRect = SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F); // This should be an exact copy of the Clip enum in painting.dart. @@ -72,9 +56,7 @@ struct PrerollContext { class Layer { public: Layer(); - virtual ~Layer(); - - virtual void Preroll(PrerollContext* context, const SkMatrix& matrix); + virtual ~Layer() = default; struct PaintContext { // When splitting the scene into multiple canvases (e.g when embedding @@ -129,28 +111,40 @@ class Layer { const SkRect bounds_; }; - virtual void Paint(PaintContext& context) const = 0; + // Performs pre-Paint() optimizations on this |Layer|. + // + // |context| is used to track global values like elevation that may vary as + // the tree of layers is traversed. + // + // |matrix| provides a transform for this layer relative to the canvas. + // + // Primarily this computes the paint_bounds() for the layer, which allows + // |Paint| to be skipped if the bounds are empty or entirely clipped. + virtual void Preroll(PrerollContext* context, const SkMatrix& matrix) = 0; #if defined(OS_FUCHSIA) - // Updates the system composited scene. - virtual void UpdateScene(SceneUpdateContext& context); + // Updates the underlying system-composited scene. This may cause new + // canvases to be created for additional system-composited layers. + virtual void UpdateScene(SceneUpdateContext& context) {} #endif + // Draws this layer to the underlying canvas. + // + // |context| contains painting-related state such as the canvas and the + // view embedder for platform views. + virtual void Paint(PaintContext& context) const = 0; + bool needs_system_composite() const { return needs_system_composite_; } void set_needs_system_composite(bool value) { needs_system_composite_ = value; } + bool needs_painting() const { return !paint_bounds_.isEmpty(); } const SkRect& paint_bounds() const { return paint_bounds_; } - - // This must be set by the time Preroll() returns otherwise the layer will - // be assumed to have empty paint bounds (paints no content). void set_paint_bounds(const SkRect& paint_bounds) { paint_bounds_ = paint_bounds; } - bool needs_painting() const { return !paint_bounds_.isEmpty(); } - uint64_t unique_id() const { return unique_id_; } private: @@ -158,8 +152,6 @@ class Layer { uint64_t unique_id_; bool needs_system_composite_; - static uint64_t NextUniqueID(); - FML_DISALLOW_COPY_AND_ASSIGN(Layer); }; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index d9e2a3859c6f8..fab545e7ac371 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -9,6 +9,10 @@ #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { LayerTree::LayerTree(const SkISize& frame_size, diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 488627362f11f..d84a457a74140 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -15,6 +15,10 @@ #include "flutter/fml/time/time_delta.h" #include "third_party/skia/include/core/SkPicture.h" +namespace scenic { + class ContainerNode; +} + namespace flutter { class LayerTree { diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index ef41cadb1ebaa..e303b8fdb7412 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -7,6 +7,10 @@ #include "flutter/fml/trace_event.h" #include "third_party/skia/include/core/SkPaint.h" +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.001f; @@ -37,8 +41,6 @@ OpacityLayer::OpacityLayer(SkAlpha opacity, const SkPoint& offset) ContainerLayer::Add(std::make_shared()); } -OpacityLayer::~OpacityLayer() = default; - void OpacityLayer::Add(std::shared_ptr layer) { GetChildContainer()->Add(std::move(layer)); } diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index d9a056789e715..d28a13a3d7de6 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -6,6 +6,8 @@ #define FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_ #include "flutter/flow/layers/container_layer.h" +#include "flutter/fml/macros.h" +#include "third_party/skia/include/core/SkPoint.h" namespace flutter { @@ -50,7 +52,7 @@ class OpacityLayer : public OpacityLayerBase { // 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() override; + ~OpacityLayer() override = default; void Add(std::shared_ptr layer) override; diff --git a/flow/layers/performance_overlay_layer.cc b/flow/layers/performance_overlay_layer.cc index ebb279c966866..d75dcaa62ed54 100644 --- a/flow/layers/performance_overlay_layer.cc +++ b/flow/layers/performance_overlay_layer.cc @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "flutter/flow/layers/performance_overlay_layer.h" + #include #include #include -#include "flutter/flow/layers/performance_overlay_layer.h" +#include "flutter/fml/trace_event.h" #include "third_party/skia/include/core/SkFont.h" namespace flutter { diff --git a/flow/layers/performance_overlay_layer.h b/flow/layers/performance_overlay_layer.h index b5c3370d2055a..bc78b4581360c 100644 --- a/flow/layers/performance_overlay_layer.h +++ b/flow/layers/performance_overlay_layer.h @@ -21,7 +21,9 @@ class PerformanceOverlayLayer : public Layer { public: explicit PerformanceOverlayLayer(uint64_t options, const char* font_path = nullptr); + ~PerformanceOverlayLayer() override = default; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override {} void Paint(PaintContext& context) const override; private: diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 45e97b4d62d39..8399f3f6eb818 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -5,8 +5,13 @@ #include "flutter/flow/layers/physical_shape_layer.h" #include "flutter/flow/paint_utils.h" +#include "flutter/fml/trace_event.h" #include "third_party/skia/include/utils/SkShadowUtils.h" +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { const SkScalar kLightHeight = 600; diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index 7d23725dcb869..22b27cff19e12 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -6,6 +6,7 @@ #define FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_ #include "flutter/flow/layers/container_layer.h" +#include "third_party/skia/include/core/SkPath.h" namespace flutter { diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index c4275e76c13cf..4a03fa26c56e4 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -4,7 +4,9 @@ #include "flutter/flow/layers/picture_layer.h" +#include "flutter/flow/raster_cache.h" #include "flutter/fml/logging.h" +#include "flutter/fml/trace_event.h" namespace flutter { @@ -17,8 +19,6 @@ PictureLayer::PictureLayer(const SkPoint& offset, is_complex_(is_complex), will_change_(will_change) {} -PictureLayer::~PictureLayer() = default; - void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkPicture* sk_picture = picture(); diff --git a/flow/layers/picture_layer.h b/flow/layers/picture_layer.h index 9c40cbef37cbd..4305e95c269f1 100644 --- a/flow/layers/picture_layer.h +++ b/flow/layers/picture_layer.h @@ -8,8 +8,9 @@ #include #include "flutter/flow/layers/layer.h" -#include "flutter/flow/raster_cache.h" #include "flutter/flow/skia_gpu_object.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/core/SkPoint.h" namespace flutter { @@ -19,14 +20,13 @@ class PictureLayer : public Layer { SkiaGPUObject picture, bool is_complex, bool will_change); - ~PictureLayer() override; - - SkPicture* picture() const { return picture_.get().get(); } + ~PictureLayer() override = default; void Preroll(PrerollContext* frame, const SkMatrix& matrix) override; - void Paint(PaintContext& context) const override; + SkPicture* picture() const { return picture_.get().get(); } + private: SkPoint offset_; // Even though pictures themselves are not GPU resources, they may reference diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 3f72993f97d66..81541b7a0cde8 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -11,8 +11,6 @@ PlatformViewLayer::PlatformViewLayer(const SkPoint& offset, int64_t view_id) : offset_(offset), size_(size), view_id_(view_id) {} -PlatformViewLayer::~PlatformViewLayer() = default; - void PlatformViewLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(), diff --git a/flow/layers/platform_view_layer.h b/flow/layers/platform_view_layer.h index 7ce7ccb58a856..d7ce602581692 100644 --- a/flow/layers/platform_view_layer.h +++ b/flow/layers/platform_view_layer.h @@ -14,7 +14,7 @@ namespace flutter { class PlatformViewLayer : public Layer { public: PlatformViewLayer(const SkPoint& offset, const SkSize& size, int64_t view_id); - ~PlatformViewLayer() override; + ~PlatformViewLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; diff --git a/flow/layers/shader_mask_layer.cc b/flow/layers/shader_mask_layer.cc index 36e7b7332aeae..92cf9667e253e 100644 --- a/flow/layers/shader_mask_layer.cc +++ b/flow/layers/shader_mask_layer.cc @@ -4,6 +4,8 @@ #include "flutter/flow/layers/shader_mask_layer.h" +#include "flutter/fml/trace_event.h" + namespace flutter { ShaderMaskLayer::ShaderMaskLayer(sk_sp shader, @@ -11,15 +13,13 @@ ShaderMaskLayer::ShaderMaskLayer(sk_sp shader, SkBlendMode blend_mode) : shader_(shader), mask_rect_(mask_rect), blend_mode_(blend_mode) {} -ShaderMaskLayer::~ShaderMaskLayer() = default; - void ShaderMaskLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ShaderMaskLayer::Paint"); FML_DCHECK(needs_painting()); Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create(context, paint_bounds(), nullptr); - PaintChildren(context); + ContainerLayer::Paint(context); SkPaint paint; paint.setBlendMode(blend_mode_); diff --git a/flow/layers/shader_mask_layer.h b/flow/layers/shader_mask_layer.h index 01836f4f2fb54..37cd51a062e1b 100644 --- a/flow/layers/shader_mask_layer.h +++ b/flow/layers/shader_mask_layer.h @@ -7,6 +7,7 @@ #include "flutter/flow/layers/container_layer.h" +#include "third_party/skia/include/core/SkBlendMode.h" #include "third_party/skia/include/core/SkShader.h" namespace flutter { @@ -16,7 +17,7 @@ class ShaderMaskLayer : public ContainerLayer { ShaderMaskLayer(sk_sp shader, const SkRect& mask_rect, SkBlendMode blend_mode); - ~ShaderMaskLayer() override; + ~ShaderMaskLayer() override = default; void Paint(PaintContext& context) const override; diff --git a/flow/layers/texture_layer.cc b/flow/layers/texture_layer.cc index c7716dd59bc29..848f69c8a115a 100644 --- a/flow/layers/texture_layer.cc +++ b/flow/layers/texture_layer.cc @@ -14,8 +14,6 @@ TextureLayer::TextureLayer(const SkPoint& offset, bool freeze) : offset_(offset), size_(size), texture_id_(texture_id), freeze_(freeze) {} -TextureLayer::~TextureLayer() = default; - void TextureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(), size_.height())); diff --git a/flow/layers/texture_layer.h b/flow/layers/texture_layer.h index 7c04471afa0c1..b533bc51da232 100644 --- a/flow/layers/texture_layer.h +++ b/flow/layers/texture_layer.h @@ -17,7 +17,7 @@ class TextureLayer : public Layer { const SkSize& size, int64_t texture_id, bool freeze); - ~TextureLayer() override; + ~TextureLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) const override; diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 5a7af132c68f2..4cb05bdaf6b85 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -4,6 +4,12 @@ #include "flutter/flow/layers/transform_layer.h" +#include "flutter/fml/trace_event.h" + +#if defined(OS_FUCHSIA) +#include "flutter/flow/scene_update_context.h" //nogncheck +#endif // defined(OS_FUCHSIA) + namespace flutter { TransformLayer::TransformLayer(const SkMatrix& transform) @@ -24,8 +30,6 @@ TransformLayer::TransformLayer(const SkMatrix& transform) } } -TransformLayer::~TransformLayer() = default; - void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkMatrix child_matrix; child_matrix.setConcat(matrix, transform_); @@ -40,12 +44,9 @@ void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { context->cull_rect = kGiantRect; } - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, child_matrix, &child_paint_bounds); - - transform_.mapRect(&child_paint_bounds); - set_paint_bounds(child_paint_bounds); + ContainerLayer::Preroll(context, child_matrix); + transform_.mapRect(paint_bounds()); context->cull_rect = previous_cull_rect; context->mutators_stack.Pop(); } @@ -56,7 +57,7 @@ void TransformLayer::UpdateScene(SceneUpdateContext& context) { FML_DCHECK(needs_system_composite()); SceneUpdateContext::Transform transform(context, transform_); - UpdateSceneChildren(context); + ContainerLayer::UpdateScene(context); } #endif // defined(OS_FUCHSIA) @@ -68,7 +69,7 @@ void TransformLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); - PaintChildren(context); + ContainerLayer::Paint(context); } } // namespace flutter diff --git a/flow/layers/transform_layer.h b/flow/layers/transform_layer.h index f19a963ced9fe..9011551d6f13e 100644 --- a/flow/layers/transform_layer.h +++ b/flow/layers/transform_layer.h @@ -6,6 +6,7 @@ #define FLUTTER_FLOW_LAYERS_TRANSFORM_LAYER_H_ #include "flutter/flow/layers/container_layer.h" +#include "third_party/skia/include/core/SkMatrix.h" namespace flutter { @@ -14,15 +15,13 @@ namespace flutter { class TransformLayer : public ContainerLayer { public: TransformLayer(const SkMatrix& transform); - ~TransformLayer() override; + ~TransformLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; - - void Paint(PaintContext& context) const override; - #if defined(OS_FUCHSIA) void UpdateScene(SceneUpdateContext& context) override; #endif // defined(OS_FUCHSIA) + void Paint(PaintContext& context) const override; private: SkMatrix transform_; diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 10a165498b4e8..0654823aa60ec 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -14,15 +14,10 @@ #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/utils/SkNWayCanvas.h" namespace flutter { -RasterCacheResult::RasterCacheResult() {} - -RasterCacheResult::RasterCacheResult(const RasterCacheResult& other) = default; - -RasterCacheResult::~RasterCacheResult() = default; - RasterCacheResult::RasterCacheResult(sk_sp image, const SkRect& logical_rect) : image_(std::move(image)), logical_rect_(logical_rect) {} diff --git a/flow/raster_cache.h b/flow/raster_cache.h index 3ea92588e1fd7..a3e4daff48777 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -19,11 +19,9 @@ namespace flutter { class RasterCacheResult { public: - RasterCacheResult(); - - RasterCacheResult(const RasterCacheResult& other); - - ~RasterCacheResult(); + RasterCacheResult() = default; + RasterCacheResult(const RasterCacheResult& other) = default; + ~RasterCacheResult() = default; RasterCacheResult(sk_sp image, const SkRect& logical_rect); diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index dfc945e48a04c..2f617667ddc30 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -15,6 +15,7 @@ #include "flutter/fml/logging.h" #include "flutter/fml/macros.h" #include "lib/ui/scenic/cpp/resources.h" +#include "lib/ui/scenic/cpp/session.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkSurface.h" diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 216e1c9284874..fc638df8783f0 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -31,12 +31,13 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/layers/child_scene_layer.h" +#include "flutter/lib/ui/compositing/scene_host.h" #endif namespace flutter { static void SceneBuilder_constructor(Dart_NativeArguments args) { - DartCallConstructor(&SceneBuilder::create, args); + DartCallConstructor(&SceneBuilder::Create, args); } IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder); @@ -78,6 +79,10 @@ void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) { }); } +fml::RefPtr SceneBuilder::Create() { + return fml::MakeRefCounted(); +} + SceneBuilder::SceneBuilder() { // Add a ContainerLayer as the root layer, so that AddLayer operations are // always valid. @@ -93,14 +98,14 @@ fml::RefPtr SceneBuilder::pushTransform( PushLayer(layer); // matrix4 has to be released before we can return another Dart object matrix4.Release(); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushOffset(double dx, double dy) { SkMatrix sk_matrix = SkMatrix::MakeTrans(dx, dy); auto layer = std::make_shared(sk_matrix); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushClipRect(double left, @@ -113,7 +118,7 @@ fml::RefPtr SceneBuilder::pushClipRect(double left, auto layer = std::make_shared(clipRect, clip_behavior); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushClipRRect(const RRect& rrect, @@ -122,7 +127,7 @@ fml::RefPtr SceneBuilder::pushClipRRect(const RRect& rrect, auto layer = std::make_shared(rrect.sk_rrect, clip_behavior); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushClipPath(const CanvasPath* path, @@ -132,7 +137,7 @@ fml::RefPtr SceneBuilder::pushClipPath(const CanvasPath* path, auto layer = std::make_shared(path->path(), clip_behavior); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushOpacity(int alpha, @@ -141,7 +146,7 @@ fml::RefPtr SceneBuilder::pushOpacity(int alpha, auto layer = std::make_shared(alpha, SkPoint::Make(dx, dy)); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushColorFilter( @@ -149,13 +154,13 @@ fml::RefPtr SceneBuilder::pushColorFilter( auto layer = std::make_shared(color_filter->filter()); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushBackdropFilter(ImageFilter* filter) { auto layer = std::make_shared(filter->filter()); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushShaderMask(Shader* shader, @@ -169,7 +174,7 @@ fml::RefPtr SceneBuilder::pushShaderMask(Shader* shader, auto layer = std::make_shared( shader->shader(), rect, static_cast(blendMode)); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); } fml::RefPtr SceneBuilder::pushPhysicalShape(const CanvasPath* path, @@ -182,15 +187,27 @@ fml::RefPtr SceneBuilder::pushPhysicalShape(const CanvasPath* path, static_cast(elevation), path->path(), static_cast(clipBehavior)); PushLayer(layer); - return EngineLayer::MakeRetained(layer); + return EngineLayer::Create(layer); +} + +void SceneBuilder::pop() { + PopLayer(); } void SceneBuilder::addRetained(fml::RefPtr retainedLayer) { AddLayer(retainedLayer->Layer()); } -void SceneBuilder::pop() { - PopLayer(); +void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, + double left, + double right, + double top, + double bottom) { + SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); + auto layer = + std::make_unique(enabledOptions); + layer->set_paint_bounds(rect); + AddLayer(std::move(layer)); } void SceneBuilder::addPicture(double dx, @@ -227,30 +244,18 @@ void SceneBuilder::addPlatformView(double dx, AddLayer(std::move(layer)); } -#if defined(OS_FUCHSIA) void SceneBuilder::addChildScene(double dx, double dy, double width, double height, SceneHost* sceneHost, bool hitTestable) { +#if defined(OS_FUCHSIA) auto layer = std::make_unique( sceneHost->id(), SkPoint::Make(dx, dy), SkSize::Make(width, height), hitTestable); AddLayer(std::move(layer)); -} #endif // defined(OS_FUCHSIA) - -void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, - double left, - double right, - double top, - double bottom) { - SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); - auto layer = - std::make_unique(enabledOptions); - layer->set_paint_bounds(rect); - AddLayer(std::move(layer)); } void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) { diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index a634087174e2f..9f4dbd5d44e33 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -22,22 +22,22 @@ #include "flutter/lib/ui/painting/shader.h" #include "third_party/tonic/typed_data/typed_list.h" -#if defined(OS_FUCHSIA) -#include "flutter/lib/ui/compositing/scene_host.h" -#endif - namespace flutter { +class SceneHost; + class SceneBuilder : public RefCountedDartWrappable { DEFINE_WRAPPERTYPEINFO(); FML_FRIEND_MAKE_REF_COUNTED(SceneBuilder); - public: - static fml::RefPtr create() { - return fml::MakeRefCounted(); - } + static void RegisterNatives(tonic::DartLibraryNatives* natives); + static fml::RefPtr Create(); + ~SceneBuilder() override; + // Container-type layers. These layers affect (are the parent of) any further + // pushed or added layers. Call |pop()| to undo the effects of the last + // pushed layer. fml::RefPtr pushTransform(tonic::Float64List& matrix4); fml::RefPtr pushOffset(double dx, double dy); fml::RefPtr pushClipRect(double left, @@ -62,40 +62,34 @@ class SceneBuilder : public RefCountedDartWrappable { int color, int shadowColor, int clipBehavior); - - void addRetained(fml::RefPtr retainedLayer); - void pop(); + // Leaf-type layers. These layers are always a child of a Container-type + // layer. + void addRetained(fml::RefPtr retainedLayer); void addPerformanceOverlay(uint64_t enabledOptions, double left, double right, double top, double bottom); - void addPicture(double dx, double dy, Picture* picture, int hints); - void addTexture(double dx, double dy, double width, double height, int64_t textureId, bool freeze); - void addPlatformView(double dx, double dy, double width, double height, int64_t viewId); - -#if defined(OS_FUCHSIA) void addChildScene(double dx, double dy, double width, double height, SceneHost* sceneHost, bool hitTestable); -#endif void setRasterizerTracingThreshold(uint32_t frameInterval); void setCheckerboardRasterCacheImages(bool checkerboard); @@ -103,8 +97,6 @@ class SceneBuilder : public RefCountedDartWrappable { fml::RefPtr build(); - static void RegisterNatives(tonic::DartLibraryNatives* natives); - private: SceneBuilder(); diff --git a/lib/ui/painting/engine_layer.cc b/lib/ui/painting/engine_layer.cc index 0868b42cc2928..236bb8a99c215 100644 --- a/lib/ui/painting/engine_layer.cc +++ b/lib/ui/painting/engine_layer.cc @@ -13,11 +13,20 @@ using tonic::ToDart; namespace flutter { +IMPLEMENT_WRAPPERTYPEINFO(ui, EngineLayer); + +#define FOR_EACH_BINDING(V) // nothing to bind + +DART_BIND_ALL(EngineLayer, FOR_EACH_BINDING) + +fml::RefPtr EngineLayer::Create( + std::shared_ptr layer) { + return fml::MakeRefCounted(layer); +} + EngineLayer::EngineLayer(std::shared_ptr layer) : layer_(layer) {} -EngineLayer::~EngineLayer() = default; - size_t EngineLayer::GetAllocationSize() { // Provide an approximation of the total memory impact of this object to the // Dart GC. The ContainerLayer may hold references to a tree of other layers, @@ -25,10 +34,4 @@ size_t EngineLayer::GetAllocationSize() { return 3000; }; -IMPLEMENT_WRAPPERTYPEINFO(ui, EngineLayer); - -#define FOR_EACH_BINDING(V) // nothing to bind - -DART_BIND_ALL(EngineLayer, FOR_EACH_BINDING) - } // namespace flutter diff --git a/lib/ui/painting/engine_layer.h b/lib/ui/painting/engine_layer.h index a679ef2fe50f3..41d1c669e3c2c 100644 --- a/lib/ui/painting/engine_layer.h +++ b/lib/ui/painting/engine_layer.h @@ -19,26 +19,21 @@ class EngineLayer; class EngineLayer : public RefCountedDartWrappable { DEFINE_WRAPPERTYPEINFO(); - + FML_FRIEND_MAKE_REF_COUNTED(EngineLayer); public: - ~EngineLayer() override; - - size_t GetAllocationSize() override; + static void RegisterNatives(tonic::DartLibraryNatives* natives); + static fml::RefPtr Create(std::shared_ptr layer); - static fml::RefPtr MakeRetained( - std::shared_ptr layer) { - return fml::MakeRefCounted(layer); - } + ~EngineLayer() override = default; - static void RegisterNatives(tonic::DartLibraryNatives* natives); + size_t GetAllocationSize() override; std::shared_ptr Layer() const { return layer_; } private: explicit EngineLayer(std::shared_ptr layer); - std::shared_ptr layer_; - FML_FRIEND_MAKE_REF_COUNTED(EngineLayer); + std::shared_ptr layer_; }; } // namespace flutter From 2718b6e5224308a3ce3bfcdb53457fa12f660741 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Wed, 23 Oct 2019 17:42:06 -0700 Subject: [PATCH 08/11] Fix CI failures --- flow/layers/physical_shape_layer.cc | 2 +- fml/logging.h | 5 +++++ shell/common/shell_test.cc | 5 +---- shell/common/shell_unittests.cc | 9 +++++++++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 8399f3f6eb818..728ac41879b86 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -22,7 +22,7 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color, float elevation, const SkPath& path, Clip clip_behavior) - : PhysicalShapeLayerBase(color, elevation, SK_AlphaOPAQUE), + : PhysicalShapeLayerBase(color, SK_AlphaOPAQUE, elevation), shadow_color_(shadow_color), path_(path), clip_behavior_(clip_behavior) { diff --git a/fml/logging.h b/fml/logging.h index 20cb887cb20df..18e46d4991887 100644 --- a/fml/logging.h +++ b/fml/logging.h @@ -89,7 +89,12 @@ bool ShouldCreateLogMessage(LogSeverity severity); #define FML_NOTREACHED() FML_DCHECK(false) +#if defined(_WIN32) +#define FML_NOTIMPLEMENTED() \ + FML_LOG(ERROR) << "Not implemented in: " << __FUNCSIG__ +#else #define FML_NOTIMPLEMENTED() \ FML_LOG(ERROR) << "Not implemented in: " << __PRETTY_FUNCTION__ +#endif #endif // FLUTTER_FML_LOGGING_H_ diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index acb46da6904a9..24de6b16c9949 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -162,10 +162,7 @@ void ShellTest::PumpOneFrame(Shell* shell, // Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized| fml::WeakPtr runtime_delegate = shell->weak_engine_; shell->GetTaskRunners().GetUITaskRunner()->PostTask( - [&latch, runtime_delegate, &builder]() { - auto viewport_metrics = - UIDartState::Current()->window()->viewport_metrics(); - + [&latch, runtime_delegate, &builder, viewport_metrics]() { auto layer_tree = std::make_unique( SkISize::Make(viewport_metrics.physical_width, viewport_metrics.physical_height), diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 9e2f6a07788ff..348b6d2df7e6d 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -600,6 +600,7 @@ TEST_F(ShellTest, WaitForFirstFrame) { fml::Status result = shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000)); ASSERT_TRUE(result.ok()); + DestroyShell(std::move(shell)); } @@ -617,7 +618,10 @@ TEST_F(ShellTest, WaitForFirstFrameZeroSizeFrame) { PumpOneFrame(shell.get(), {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); fml::Status result = shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000)); + ASSERT_FALSE(result.ok()); ASSERT_EQ(result.code(), fml::StatusCode::kDeadlineExceeded); + + DestroyShell(std::move(shell)); } TEST_F(ShellTest, WaitForFirstFrameTimeout) { @@ -633,7 +637,9 @@ TEST_F(ShellTest, WaitForFirstFrameTimeout) { RunEngine(shell.get(), std::move(configuration)); fml::Status result = shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(10)); + ASSERT_FALSE(result.ok()); ASSERT_EQ(result.code(), fml::StatusCode::kDeadlineExceeded); + DestroyShell(std::move(shell)); } @@ -656,6 +662,7 @@ TEST_F(ShellTest, WaitForFirstFrameMultiple) { result = shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1)); ASSERT_TRUE(result.ok()); } + DestroyShell(std::move(shell)); } @@ -681,10 +688,12 @@ TEST_F(ShellTest, WaitForFirstFrameInlined) { task_runner->PostTask([&shell, &event] { fml::Status result = shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000)); + ASSERT_FALSE(result.ok()); ASSERT_EQ(result.code(), fml::StatusCode::kFailedPrecondition); event.Signal(); }); ASSERT_FALSE(event.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(1000))); + DestroyShell(std::move(shell), std::move(task_runners)); } From 1cd39d79a238f80d7c68b1315445db1dedc89501 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Sat, 9 Nov 2019 03:42:54 -0800 Subject: [PATCH 09/11] Add tests --- flow/layers/physical_shape_layer_unittests.cc | 299 +++++++++++++++--- 1 file changed, 261 insertions(+), 38 deletions(-) diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index 241b701e4e475..12a246ed58f91 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -5,64 +5,287 @@ #include "flutter/flow/layers/physical_shape_layer.h" #include "gtest/gtest.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" +#include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/utils/SkNWayCanvas.h" namespace flutter { -TEST(PhysicalShapeLayer, TotalElevation) { - std::shared_ptr layers[4]; +class MockCanvas : public SkCanvasVirtualEnforcer { + public: + MockCanvas(int width, int height) + : SkCanvasVirtualEnforcer(width, height) {} - SkColor dummy_color = 0; - SkPath dummy_path; - for (int i = 0; i < 4; i += 1) { - layers[i] = - std::make_shared(dummy_color, dummy_color, - (float)(i + 1), // elevation - dummy_path, Clip::none); - } +protected: + SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override { + (void)SkCanvasVirtualEnforcer::getSaveLayerStrategy(rec); + return kNoLayer_SaveLayerStrategy; + } + bool onDoSaveBehind(const SkRect*) override { FML_DCHECK(false); return false; } - layers[0]->Add(layers[1]); - layers[0]->Add(layers[2]); - layers[2]->Add(layers[3]); + // No-op overrides for aborting rasterization earlier than SkNullBlitter. + void onDrawAnnotation(const SkRect&, const char[], SkData*) override { FML_DCHECK(false); } + void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override { FML_DCHECK(false); } + void onDrawDrawable(SkDrawable*, const SkMatrix*) override { FML_DCHECK(false); } + void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override { FML_DCHECK(false); } + void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode, + const SkPaint&) override { FML_DCHECK(false); } + + void onDrawPaint(const SkPaint&) override { FML_DCHECK(false); } + void onDrawBehind(const SkPaint&) override { FML_DCHECK(false); } + void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override { FML_DCHECK(false); } + void onDrawRect(const SkRect&, const SkPaint&) override { FML_DCHECK(false); } + void onDrawRegion(const SkRegion&, const SkPaint&) override { FML_DCHECK(false); } + void onDrawOval(const SkRect&, const SkPaint&) override { FML_DCHECK(false); } + void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override { FML_DCHECK(false); } + void onDrawRRect(const SkRRect&, const SkPaint&) override { FML_DCHECK(false); } + void onDrawPath(const SkPath&, const SkPaint&) override { FML_DCHECK(false); } + void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override { FML_DCHECK(false); } + void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*, + SrcRectConstraint) override { FML_DCHECK(false); } + void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override { FML_DCHECK(false); } + void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*, + SrcRectConstraint) override { FML_DCHECK(false); } + void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override { FML_DCHECK(false); } + void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, + const SkPaint*) override { FML_DCHECK(false); } + void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, + const SkPaint*) override { FML_DCHECK(false); } + void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&, + const SkPaint*) override { FML_DCHECK(false); } + void onDrawVerticesObject(const SkVertices*, const SkVertices::Bone[], int, SkBlendMode, + const SkPaint&) override { FML_DCHECK(false); } + void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], + int, SkBlendMode, const SkRect*, const SkPaint*) override { FML_DCHECK(false); } + void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override { FML_DCHECK(false); } + void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override { FML_DCHECK(false); } + + void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], QuadAAFlags, const SkColor4f&, + SkBlendMode) override { FML_DCHECK(false); } + void onDrawEdgeAAImageSet(const ImageSetEntry[], int, const SkPoint[], + const SkMatrix[], const SkPaint*, SrcRectConstraint) override { FML_DCHECK(false); } +}; + +class PhysicalShapeLayerTestMockCanvas : public MockCanvas { + public: + struct PathDrawCall { + SkPath path; + SkPaint paint; + }; - const Stopwatch unused_stopwatch; - TextureRegistry unused_texture_registry; - MutatorsStack unused_stack; - PrerollContext preroll_context{ - nullptr, // raster_cache (don't consult the cache) - nullptr, // gr_context (used for the raster cache) - nullptr, // external view embedder - unused_stack, // mutator stack - nullptr, // SkColorSpace* dst_color_space - kGiantRect, // SkRect cull_rect - unused_stopwatch, // frame time (dont care) - unused_stopwatch, // engine time (dont care) - unused_texture_registry, // texture registry (not supported) - false, // checkerboard_offscreen_layers - 6.0f, // physical depth - 1.0f, // device pixel ratio - 0.0f, // total elevation + struct ShadowRecDrawCall { + const SkPath& path; + const SkDrawShadowRec& rec; }; - SkMatrix identity; - identity.setIdentity(); + PhysicalShapeLayerTestMockCanvas(int width, int height) : MockCanvas(width, height) {} + + const std::vector path_draw_calls() const { + return path_draw_calls_; + } + const std::vector shadow_draw_calls() const { + return shadow_draw_calls_; + } + + private: + void onDrawPath(const SkPath& path, const SkPaint& paint) override { + path_draw_calls_.emplace_back(PathDrawCall({path, paint})); + } + void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override { + shadow_draw_calls_.emplace_back(ShadowRecDrawCall({path, rec})); + } + + std::vector path_draw_calls_; + std::vector shadow_draw_calls_; +}; + +class LayerTest : public testing::Test { + public: + LayerTest() + : canvas_(16, 16), + internal_nodes_canvas_(canvas_.imageInfo().width(), + canvas_.imageInfo().height()), + preroll_context_({ + nullptr, // raster_cache (don't consult the cache) + nullptr, // gr_context (don't care) + nullptr, // external view embedder + mutator_stack_, // mutator stack + canvas_.imageInfo().colorSpace(), // dst_color_space + kGiantRect, // SkRect cull_rect + stopwatch_, // frame time (dont care) + stopwatch_, // engine time (dont care) + texture_registry_, // texture registry (not supported) + false, // checkerboard_offscreen_layers + 1000.0f, // physical depth + 1.0f, // device pixel ratio + 0.0f, // total elevation + }), + paint_context_({ + &internal_nodes_canvas_, // internal_nodes_canvase + &canvas_, // leaf_nodes_canvas + nullptr, // gr_context (don't care) + nullptr, // view_embedder (don't care) + stopwatch_, // raster_time (don't care) + stopwatch_, // ui_time (don't care) + texture_registry_, // texture_registry (don't care) + nullptr, // raster_cache (don't consult the cache) + false, // checkerboard_offscreen_layers + 10000.0f, // frame_physical_depth + 1.0f, // frame_device_pixel_ratio + }) {} + + protected: + PhysicalShapeLayerTestMockCanvas canvas_; + const Stopwatch stopwatch_; + MutatorsStack mutator_stack_; + TextureRegistry texture_registry_; + SkNWayCanvas internal_nodes_canvas_; + PrerollContext preroll_context_; + Layer::PaintContext paint_context_; +}; + +using PhysicalShapeLayerTest = LayerTest; + +TEST_F(PhysicalShapeLayerTest, EmptyLayer) { + auto layer = std::make_shared(SK_ColorGREEN, + SK_ColorBLACK, + 0.0f, // elevation + SkPath(), Clip::none); + + layer->Preroll(&preroll_context_, SkMatrix()); + EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); + EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_system_composite()); + + EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context_), ""); +} + +TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) { + SkPath layer_path; + + layer_path.addRect(0, 8, 8, 0).close(); + auto layer = std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 0.0f, // elevation + layer_path, + Clip::none); + layer->Preroll(&preroll_context_, SkMatrix()); + EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds()); + EXPECT_TRUE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_system_composite()); + + layer->Paint(paint_context_); + EXPECT_EQ(canvas_.path_draw_calls().size(), 1u); + EXPECT_EQ(canvas_.shadow_draw_calls().size(), 0u); + EXPECT_EQ(canvas_.path_draw_calls()[0].path, layer_path); + EXPECT_EQ(canvas_.path_draw_calls()[0].paint.getColor(), SK_ColorGREEN); +} + +TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPath) { + SkPath layer_path, child1_path, child2_path; + SkRect child_paint_bounds; + + layer_path.addRect(0, 8, 8, 0).close(); + child1_path.addRect(4, 12, 12, 0).close(); + child2_path.addRect(3, 15, 5, 2).close(); + auto child1 = std::make_shared(SK_ColorRED, + SK_ColorBLACK, + 0.0f, // elevation + child1_path, + Clip::none); + auto child2 = std::make_shared(SK_ColorBLUE, + SK_ColorBLACK, + 0.0f, // elevation + child2_path, + Clip::none); + auto layer = std::make_shared(SK_ColorGREEN, + SK_ColorBLACK, + 0.0f, // elevation + layer_path, + Clip::none); + layer->Add(child1); + layer->Add(child2); + + layer->Preroll(&preroll_context_, SkMatrix()); + child_paint_bounds.join(child1->paint_bounds()); + child_paint_bounds.join(child2->paint_bounds()); + EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds()); + EXPECT_NE(layer->paint_bounds(), SkRect::MakeEmpty()); + EXPECT_NE(layer->paint_bounds(), child_paint_bounds); + + layer->Paint(paint_context_); + EXPECT_EQ(canvas_.path_draw_calls().size(), 3u); + EXPECT_EQ(canvas_.shadow_draw_calls().size(), 0u); + EXPECT_EQ(canvas_.path_draw_calls()[0].path, layer_path); + EXPECT_EQ(canvas_.path_draw_calls()[0].paint.getColor(), SK_ColorGREEN); + EXPECT_EQ(canvas_.path_draw_calls()[1].path, child1_path); + EXPECT_EQ(canvas_.path_draw_calls()[1].paint.getColor(), SK_ColorRED); + EXPECT_EQ(canvas_.path_draw_calls()[2].path, child2_path); + EXPECT_EQ(canvas_.path_draw_calls()[2].paint.getColor(), SK_ColorBLUE); +} + +TEST_F(PhysicalShapeLayerTest, ElevationSimple) { + SkPath layer_path; + + layer_path.addRect(0, 8, 8, 0).close(); + auto layer = std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 20.0f, // elevation + layer_path, + Clip::none); - layers[0]->Preroll(&preroll_context, identity); + preroll_context_.frame_physical_depth = 10.0f; // Clamp depth + layer->Preroll(&preroll_context_, SkMatrix()); + EXPECT_NE(layer->paint_bounds(), layer_path.getBounds()); + EXPECT_EQ(layer->elevation(), 10.0f); + EXPECT_EQ(layer->total_elevation(), 10.0f); + EXPECT_TRUE(layer->needs_painting()); + EXPECT_EQ(layer->needs_system_composite(), PhysicalShapeLayerBase::should_system_composite()); - // It should look like this: - // layers[0] +1.0f + layer->Paint(paint_context_); + EXPECT_EQ(canvas_.path_draw_calls().size(), 1u); + EXPECT_EQ(canvas_.shadow_draw_calls().size(), 1u); + EXPECT_EQ(canvas_.path_draw_calls()[0].path, layer_path); + EXPECT_EQ(canvas_.path_draw_calls()[0].paint.getColor(), SK_ColorGREEN); + EXPECT_EQ(canvas_.shadow_draw_calls()[0].path, layer_path); +} + +TEST_F(PhysicalShapeLayerTest, ElevationComplex) { + // The layer tree should look like this: + // layers[0] +1.0f = 1.0f // | \ // | \ // | \ - // | layers[2] +3.0f + // | layers[2] +3.0f = 4.0f // | | - // | layers[3] +4.0f (clamped to 6.0f) + // | layers[3] +4.0f = 8.0f (clamped to 6.0f) // | // | - // layers[1] + 2.0f + // layers[1] + 2.0f = 3.0f + std::shared_ptr layers[4]; + for (int i = 0; i < 4; i += 1) { + layers[i] = + std::make_shared(SK_ColorBLACK, SK_ColorBLACK, + (float)(i + 1), // elevation + SkPath(), Clip::none); + } + layers[0]->Add(layers[1]); + layers[0]->Add(layers[2]); + layers[2]->Add(layers[3]); + + preroll_context_.frame_physical_depth = 6.0f; // Clamp depth + layers[0]->Preroll(&preroll_context_, SkMatrix()); + EXPECT_EQ(layers[0]->elevation(), 1.0f); + EXPECT_EQ(layers[1]->elevation(), 2.0f); + EXPECT_EQ(layers[2]->elevation(), 3.0f); + EXPECT_EQ(layers[3]->elevation(), 2.0f); EXPECT_EQ(layers[0]->total_elevation(), 1.0f); EXPECT_EQ(layers[1]->total_elevation(), 3.0f); EXPECT_EQ(layers[2]->total_elevation(), 4.0f); EXPECT_EQ(layers[3]->total_elevation(), 6.0f); + + layers[0]->Paint(paint_context_); + EXPECT_EQ(canvas_.path_draw_calls().size(), 4u); + EXPECT_EQ(canvas_.shadow_draw_calls().size(), 4u); } } // namespace flutter From 891651c04b1690760d7f154c643de7971c7365a6 Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 11 Nov 2019 14:45:18 -0800 Subject: [PATCH 10/11] Break out test fixture and add more tests --- flow/BUILD.gn | 4 + flow/layers/layer_test.cc | 53 ++++++ flow/layers/layer_test.h | 34 ++++ flow/layers/opacity_layer_unittests.cc | 49 +++++ flow/layers/physical_shape_layer_unittests.cc | 133 ++------------ testing/BUILD.gn | 2 + testing/mock_canvas.cc | 167 ++++++++++++++++++ testing/mock_canvas.h | 127 +++++++++++++ 8 files changed, 454 insertions(+), 115 deletions(-) create mode 100644 flow/layers/layer_test.cc create mode 100644 flow/layers/layer_test.h create mode 100644 flow/layers/opacity_layer_unittests.cc create mode 100644 testing/mock_canvas.cc create mode 100644 testing/mock_canvas.h diff --git a/flow/BUILD.gn b/flow/BUILD.gn index c2f0c98415a3e..44ab616cac9e5 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -109,7 +109,10 @@ executable("flow_unittests") { "flow_run_all_unittests.cc", "flow_test_utils.cc", "flow_test_utils.h", + "layers/layer_test.cc", + "layers/layer_test.h", "layers/performance_overlay_layer_unittests.cc", + "layers/opacity_layer_unittests.cc", "layers/physical_shape_layer_unittests.cc", "matrix_decomposition_unittests.cc", "mutators_stack_unittests.cc", @@ -122,6 +125,7 @@ executable("flow_unittests") { ":flow", ":flow_fixtures", "$flutter_root/fml", + "$flutter_root/testing:skia", "$flutter_root/testing:testing_lib", "//third_party/dart/runtime:libdart_jit", # for tracing "//third_party/googletest:gtest", diff --git a/flow/layers/layer_test.cc b/flow/layers/layer_test.cc new file mode 100644 index 0000000000000..2a6c16b93d8e4 --- /dev/null +++ b/flow/layers/layer_test.cc @@ -0,0 +1,53 @@ +// Copyright 2019 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/layer_test.h" + +#include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/utils/SkNWayCanvas.h" + +namespace flutter { +namespace testing { +namespace { + +PrerollContext CreatePrerollContext(MockCanvas* canvas, Stopwatch& stopwatch, MutatorsStack& mutators_stack, TextureRegistry& texture_registry) { + return { + nullptr, // raster_cache (don't care) + nullptr, // gr_context (don't care) + nullptr, // external view embedder + mutators_stack, // mutator stack + canvas->imageInfo().colorSpace(), // dst_color_space + kGiantRect, // SkRect cull_rect + stopwatch, // frame time (dont care) + stopwatch, // engine time (dont care) + texture_registry, // texture registry (dont care) + false, // checkerboard_offscreen_layers + 1000.0f, // physical depth + 1.0f, // device pixel ratio + 0.0f, // total elevation + }; +} + +Layer::PaintContext CreatePaintContext(MockCanvas* canvas, Stopwatch& stopwatch, TextureRegistry& texture_registry) { + return { + canvas->GetInternalCanvas(), // internal_nodes_canvas + canvas, // leaf_nodes_canvas + nullptr, // gr_context (don't care) + nullptr, // view_embedder (don't care) + stopwatch, // raster_time (don't care) + stopwatch, // ui_time (don't care) + texture_registry, // texture_registry (don't care) + nullptr, // raster_cache (don't care) + false, // checkerboard_offscreen_layers + 10000.0f, // frame_physical_depth + 1.0f, // frame_device_pixel_ratio + }; +} + +} // namespace + +LayerTest::LayerTest(MockCanvas* canvas) : preroll_context_(CreatePrerollContext(canvas, stopwatch_, mutators_stack_, texture_registry_)), paint_context_(CreatePaintContext(canvas, stopwatch_, texture_registry_)) {} + +} // namespace testing +} // namespace flutter diff --git a/flow/layers/layer_test.h b/flow/layers/layer_test.h new file mode 100644 index 0000000000000..15a4bb3e03fc7 --- /dev/null +++ b/flow/layers/layer_test.h @@ -0,0 +1,34 @@ +// Copyright 2019 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 TESTING_LAYER_TEST_H_ +#define TESTING_LAYER_TEST_H_ + +#include "gtest/gtest.h" +#include "flutter/flow/layers/layer.h" +#include "flutter/testing/mock_canvas.h" + +namespace flutter { +namespace testing { + +class LayerTest : public ::testing::Test { + public: + LayerTest(MockCanvas* canvas); + virtual ~LayerTest() = default; + + PrerollContext* preroll_context() { return &preroll_context_; } + Layer::PaintContext& paint_context() { return paint_context_; } + + protected: + Stopwatch stopwatch_; + MutatorsStack mutators_stack_; + TextureRegistry texture_registry_; + PrerollContext preroll_context_; + Layer::PaintContext paint_context_; +}; + +} // namespace testing +} // namespace flutter + +#endif // TESTING_LAYER_TEST_H_ diff --git a/flow/layers/opacity_layer_unittests.cc b/flow/layers/opacity_layer_unittests.cc new file mode 100644 index 0000000000000..5964ae42fa87e --- /dev/null +++ b/flow/layers/opacity_layer_unittests.cc @@ -0,0 +1,49 @@ +// Copyright 2019 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/opacity_layer.h" + +#include "flutter/flow/layers/layer_test.h" +#include "flutter/testing/mock_canvas.h" + +namespace flutter { + +class OpacityLayerTestMockCanvas : public testing::MockCanvas { + public: + struct PathDrawCall { + SkPath path; + SkPaint paint; + }; + + OpacityLayerTestMockCanvas(int width, int height) + : testing::MockCanvas(width, height) {} + + const std::vector path_draw_calls() const { + return path_draw_calls_; + } + + private: + void onDrawPath(const SkPath& path, const SkPaint& paint) override { + path_draw_calls_.emplace_back(PathDrawCall({path, paint})); + } + + std::vector path_draw_calls_; +}; + +class OpacityLayerTest : public testing::LayerTest { + public: + OpacityLayerTest() : LayerTest(&canvas_), canvas_(16, 16) {} + + protected: + OpacityLayerTestMockCanvas canvas_; +}; + +TEST_F(OpacityLayerTest, EmptyLayer) { + auto layer = + std::make_shared(SK_AlphaOPAQUE, SkPoint::Make(0.0f, 0.0f)); + + EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()), ""); +} + +} // namespace flutter diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index 12a246ed58f91..2efd1e576e830 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -4,70 +4,12 @@ #include "flutter/flow/layers/physical_shape_layer.h" -#include "gtest/gtest.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" -#include "third_party/skia/include/core/SkImageInfo.h" -#include "third_party/skia/include/utils/SkNWayCanvas.h" +#include "flutter/flow/layers/layer_test.h" +#include "flutter/testing/mock_canvas.h" namespace flutter { -class MockCanvas : public SkCanvasVirtualEnforcer { - public: - MockCanvas(int width, int height) - : SkCanvasVirtualEnforcer(width, height) {} - -protected: - SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override { - (void)SkCanvasVirtualEnforcer::getSaveLayerStrategy(rec); - return kNoLayer_SaveLayerStrategy; - } - bool onDoSaveBehind(const SkRect*) override { FML_DCHECK(false); return false; } - - // No-op overrides for aborting rasterization earlier than SkNullBlitter. - void onDrawAnnotation(const SkRect&, const char[], SkData*) override { FML_DCHECK(false); } - void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override { FML_DCHECK(false); } - void onDrawDrawable(SkDrawable*, const SkMatrix*) override { FML_DCHECK(false); } - void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override { FML_DCHECK(false); } - void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode, - const SkPaint&) override { FML_DCHECK(false); } - - void onDrawPaint(const SkPaint&) override { FML_DCHECK(false); } - void onDrawBehind(const SkPaint&) override { FML_DCHECK(false); } - void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override { FML_DCHECK(false); } - void onDrawRect(const SkRect&, const SkPaint&) override { FML_DCHECK(false); } - void onDrawRegion(const SkRegion&, const SkPaint&) override { FML_DCHECK(false); } - void onDrawOval(const SkRect&, const SkPaint&) override { FML_DCHECK(false); } - void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override { FML_DCHECK(false); } - void onDrawRRect(const SkRRect&, const SkPaint&) override { FML_DCHECK(false); } - void onDrawPath(const SkPath&, const SkPaint&) override { FML_DCHECK(false); } - void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override { FML_DCHECK(false); } - void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*, - SrcRectConstraint) override { FML_DCHECK(false); } - void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override { FML_DCHECK(false); } - void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*, - SrcRectConstraint) override { FML_DCHECK(false); } - void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override { FML_DCHECK(false); } - void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, - const SkPaint*) override { FML_DCHECK(false); } - void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, - const SkPaint*) override { FML_DCHECK(false); } - void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&, - const SkPaint*) override { FML_DCHECK(false); } - void onDrawVerticesObject(const SkVertices*, const SkVertices::Bone[], int, SkBlendMode, - const SkPaint&) override { FML_DCHECK(false); } - void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], - int, SkBlendMode, const SkRect*, const SkPaint*) override { FML_DCHECK(false); } - void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override { FML_DCHECK(false); } - void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override { FML_DCHECK(false); } - - void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], QuadAAFlags, const SkColor4f&, - SkBlendMode) override { FML_DCHECK(false); } - void onDrawEdgeAAImageSet(const ImageSetEntry[], int, const SkPoint[], - const SkMatrix[], const SkPaint*, SrcRectConstraint) override { FML_DCHECK(false); } -}; - -class PhysicalShapeLayerTestMockCanvas : public MockCanvas { +class PhysicalShapeLayerTestMockCanvas : public testing::MockCanvas { public: struct PathDrawCall { SkPath path; @@ -79,8 +21,8 @@ class PhysicalShapeLayerTestMockCanvas : public MockCanvas { const SkDrawShadowRec& rec; }; - PhysicalShapeLayerTestMockCanvas(int width, int height) : MockCanvas(width, height) {} - + PhysicalShapeLayerTestMockCanvas(int width, int height) : testing::MockCanvas(width, height) {} + const std::vector path_draw_calls() const { return path_draw_calls_; } @@ -100,65 +42,26 @@ class PhysicalShapeLayerTestMockCanvas : public MockCanvas { std::vector shadow_draw_calls_; }; -class LayerTest : public testing::Test { +class PhysicalShapeLayerTest : public testing::LayerTest { public: - LayerTest() - : canvas_(16, 16), - internal_nodes_canvas_(canvas_.imageInfo().width(), - canvas_.imageInfo().height()), - preroll_context_({ - nullptr, // raster_cache (don't consult the cache) - nullptr, // gr_context (don't care) - nullptr, // external view embedder - mutator_stack_, // mutator stack - canvas_.imageInfo().colorSpace(), // dst_color_space - kGiantRect, // SkRect cull_rect - stopwatch_, // frame time (dont care) - stopwatch_, // engine time (dont care) - texture_registry_, // texture registry (not supported) - false, // checkerboard_offscreen_layers - 1000.0f, // physical depth - 1.0f, // device pixel ratio - 0.0f, // total elevation - }), - paint_context_({ - &internal_nodes_canvas_, // internal_nodes_canvase - &canvas_, // leaf_nodes_canvas - nullptr, // gr_context (don't care) - nullptr, // view_embedder (don't care) - stopwatch_, // raster_time (don't care) - stopwatch_, // ui_time (don't care) - texture_registry_, // texture_registry (don't care) - nullptr, // raster_cache (don't consult the cache) - false, // checkerboard_offscreen_layers - 10000.0f, // frame_physical_depth - 1.0f, // frame_device_pixel_ratio - }) {} + PhysicalShapeLayerTest() : LayerTest(&canvas_), canvas_(16, 16) {} protected: PhysicalShapeLayerTestMockCanvas canvas_; - const Stopwatch stopwatch_; - MutatorsStack mutator_stack_; - TextureRegistry texture_registry_; - SkNWayCanvas internal_nodes_canvas_; - PrerollContext preroll_context_; - Layer::PaintContext paint_context_; }; -using PhysicalShapeLayerTest = LayerTest; - TEST_F(PhysicalShapeLayerTest, EmptyLayer) { auto layer = std::make_shared(SK_ColorGREEN, SK_ColorBLACK, 0.0f, // elevation SkPath(), Clip::none); - layer->Preroll(&preroll_context_, SkMatrix()); + layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); EXPECT_FALSE(layer->needs_painting()); EXPECT_FALSE(layer->needs_system_composite()); - EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context_), ""); + EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), ""); } TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) { @@ -174,7 +77,7 @@ TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) { EXPECT_TRUE(layer->needs_painting()); EXPECT_FALSE(layer->needs_system_composite()); - layer->Paint(paint_context_); + layer->Paint(paint_context()); EXPECT_EQ(canvas_.path_draw_calls().size(), 1u); EXPECT_EQ(canvas_.shadow_draw_calls().size(), 0u); EXPECT_EQ(canvas_.path_draw_calls()[0].path, layer_path); @@ -206,14 +109,14 @@ TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPath) { layer->Add(child1); layer->Add(child2); - layer->Preroll(&preroll_context_, SkMatrix()); + layer->Preroll(preroll_context(), SkMatrix()); child_paint_bounds.join(child1->paint_bounds()); child_paint_bounds.join(child2->paint_bounds()); EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds()); EXPECT_NE(layer->paint_bounds(), SkRect::MakeEmpty()); EXPECT_NE(layer->paint_bounds(), child_paint_bounds); - layer->Paint(paint_context_); + layer->Paint(paint_context()); EXPECT_EQ(canvas_.path_draw_calls().size(), 3u); EXPECT_EQ(canvas_.shadow_draw_calls().size(), 0u); EXPECT_EQ(canvas_.path_draw_calls()[0].path, layer_path); @@ -233,15 +136,15 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) { layer_path, Clip::none); - preroll_context_.frame_physical_depth = 10.0f; // Clamp depth - layer->Preroll(&preroll_context_, SkMatrix()); + preroll_context()->frame_physical_depth = 10.0f; // Clamp depth + layer->Preroll(preroll_context(), SkMatrix()); EXPECT_NE(layer->paint_bounds(), layer_path.getBounds()); EXPECT_EQ(layer->elevation(), 10.0f); EXPECT_EQ(layer->total_elevation(), 10.0f); EXPECT_TRUE(layer->needs_painting()); EXPECT_EQ(layer->needs_system_composite(), PhysicalShapeLayerBase::should_system_composite()); - layer->Paint(paint_context_); + layer->Paint(paint_context()); EXPECT_EQ(canvas_.path_draw_calls().size(), 1u); EXPECT_EQ(canvas_.shadow_draw_calls().size(), 1u); EXPECT_EQ(canvas_.path_draw_calls()[0].path, layer_path); @@ -272,8 +175,8 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) { layers[0]->Add(layers[2]); layers[2]->Add(layers[3]); - preroll_context_.frame_physical_depth = 6.0f; // Clamp depth - layers[0]->Preroll(&preroll_context_, SkMatrix()); + preroll_context()->frame_physical_depth = 6.0f; // Clamp depth + layers[0]->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layers[0]->elevation(), 1.0f); EXPECT_EQ(layers[1]->elevation(), 2.0f); EXPECT_EQ(layers[2]->elevation(), 3.0f); @@ -283,7 +186,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) { EXPECT_EQ(layers[2]->total_elevation(), 4.0f); EXPECT_EQ(layers[3]->total_elevation(), 6.0f); - layers[0]->Paint(paint_context_); + layers[0]->Paint(paint_context()); EXPECT_EQ(canvas_.path_draw_calls().size(), 4u); EXPECT_EQ(canvas_.shadow_draw_calls().size(), 4u); } diff --git a/testing/BUILD.gn b/testing/BUILD.gn index a8db2229e29f5..9b2b43965aee4 100644 --- a/testing/BUILD.gn +++ b/testing/BUILD.gn @@ -52,6 +52,8 @@ source_set("skia") { sources = [ "$flutter_root/testing/assertions_skia.h", + "$flutter_root/testing/mock_canvas.cc", + "$flutter_root/testing/mock_canvas.h", ] public_deps = [ diff --git a/testing/mock_canvas.cc b/testing/mock_canvas.cc new file mode 100644 index 0000000000000..0e79cb5e81f03 --- /dev/null +++ b/testing/mock_canvas.cc @@ -0,0 +1,167 @@ +// Copyright 2019 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/testing/mock_canvas.h" + +#include "flutter/fml/logging.h" +#include "third_party/skia/include/core/SkImageInfo.h" + +namespace flutter { +namespace testing { + +MockCanvas::MockCanvas(int width, int height) + : SkCanvasVirtualEnforcer(width, height), + internal_canvas_(imageInfo().width(), imageInfo().height()) {} + +SkCanvas::SaveLayerStrategy MockCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { + (void)SkCanvasVirtualEnforcer::getSaveLayerStrategy(rec); + return kNoLayer_SaveLayerStrategy; +} + +bool MockCanvas::onDoSaveBehind(const SkRect*) { + FML_DCHECK(false); + return false; +} + +void MockCanvas::onDrawAnnotation(const SkRect&, const char[], SkData*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawDrawable(SkDrawable*, const SkMatrix*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawTextBlob(const SkTextBlob*, + SkScalar, + SkScalar, + const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawPatch(const SkPoint[12], + const SkColor[4], + const SkPoint[4], + SkBlendMode, + const SkPaint&) { + FML_DCHECK(false); +} + +void MockCanvas::onDrawPaint(const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawBehind(const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawPoints(PointMode, + size_t, + const SkPoint[], + const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawRect(const SkRect&, const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawRegion(const SkRegion&, const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawOval(const SkRect&, const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawArc(const SkRect&, + SkScalar, + SkScalar, + bool, + const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawRRect(const SkRRect&, const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawPath(const SkPath&, const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawBitmap(const SkBitmap&, + SkScalar, + SkScalar, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawBitmapRect(const SkBitmap&, + const SkRect*, + const SkRect&, + const SkPaint*, + SrcRectConstraint) { + FML_DCHECK(false); +} +void MockCanvas::onDrawImage(const SkImage*, + SkScalar, + SkScalar, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawImageRect(const SkImage*, + const SkRect*, + const SkRect&, + const SkPaint*, + SrcRectConstraint) { + FML_DCHECK(false); +} +void MockCanvas::onDrawImageNine(const SkImage*, + const SkIRect&, + const SkRect&, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawBitmapNine(const SkBitmap&, + const SkIRect&, + const SkRect&, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawImageLattice(const SkImage*, + const Lattice&, + const SkRect&, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawBitmapLattice(const SkBitmap&, + const Lattice&, + const SkRect&, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawVerticesObject(const SkVertices*, + const SkVertices::Bone[], + int, + SkBlendMode, + const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawAtlas(const SkImage*, + const SkRSXform[], + const SkRect[], + const SkColor[], + int, + SkBlendMode, + const SkRect*, + const SkPaint*) { + FML_DCHECK(false); +} +void MockCanvas::onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawPicture(const SkPicture*, + const SkMatrix*, + const SkPaint*) { + FML_DCHECK(false); +} + +void MockCanvas::onDrawEdgeAAQuad(const SkRect&, + const SkPoint[4], + QuadAAFlags, + const SkColor4f&, + SkBlendMode) { + FML_DCHECK(false); +} +void MockCanvas::onDrawEdgeAAImageSet(const ImageSetEntry[], + int, + const SkPoint[], + const SkMatrix[], + const SkPaint*, + SrcRectConstraint) { + FML_DCHECK(false); +} + +} // namespace testing +} // namespace flutter diff --git a/testing/mock_canvas.h b/testing/mock_canvas.h new file mode 100644 index 0000000000000..58fb1cf23ce89 --- /dev/null +++ b/testing/mock_canvas.h @@ -0,0 +1,127 @@ +// Copyright 2019 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 TESTING_MOCK_CANVAS_H_ +#define TESTING_MOCK_CANVAS_H_ + +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" +#include "third_party/skia/include/utils/SkNWayCanvas.h" + +namespace flutter { +namespace testing { + +class MockCanvas : public SkCanvasVirtualEnforcer { + public: + MockCanvas(int width, int height); + virtual ~MockCanvas() = default; + + SkNWayCanvas* GetInternalCanvas() { return &internal_canvas_; } + + protected: + SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; + bool onDoSaveBehind(const SkRect*) override; + + // No-op overrides for aborting rasterization earlier than SkNullBlitter. + void onDrawAnnotation(const SkRect&, const char[], SkData*) override; + void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; + void onDrawDrawable(SkDrawable*, const SkMatrix*) override; + void onDrawTextBlob(const SkTextBlob*, + SkScalar, + SkScalar, + const SkPaint&) override; + void onDrawPatch(const SkPoint[12], + const SkColor[4], + const SkPoint[4], + SkBlendMode, + const SkPaint&) override; + + void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; + void onDrawPoints(PointMode, + size_t, + const SkPoint[], + const SkPaint&) override; + void onDrawRect(const SkRect&, const SkPaint&) override; + void onDrawRegion(const SkRegion&, const SkPaint&) override; + void onDrawOval(const SkRect&, const SkPaint&) override; + void onDrawArc(const SkRect&, + SkScalar, + SkScalar, + bool, + const SkPaint&) override; + void onDrawRRect(const SkRRect&, const SkPaint&) override; + void onDrawPath(const SkPath&, const SkPaint&) override; + void onDrawBitmap(const SkBitmap&, + SkScalar, + SkScalar, + const SkPaint*) override; + void onDrawBitmapRect(const SkBitmap&, + const SkRect*, + const SkRect&, + const SkPaint*, + SrcRectConstraint) override; + void onDrawImage(const SkImage*, + SkScalar, + SkScalar, + const SkPaint*) override; + void onDrawImageRect(const SkImage*, + const SkRect*, + const SkRect&, + const SkPaint*, + SrcRectConstraint) override; + void onDrawImageNine(const SkImage*, + const SkIRect&, + const SkRect&, + const SkPaint*) override; + void onDrawBitmapNine(const SkBitmap&, + const SkIRect&, + const SkRect&, + const SkPaint*) override; + void onDrawImageLattice(const SkImage*, + const Lattice&, + const SkRect&, + const SkPaint*) override; + void onDrawBitmapLattice(const SkBitmap&, + const Lattice&, + const SkRect&, + const SkPaint*) override; + void onDrawVerticesObject(const SkVertices*, + const SkVertices::Bone[], + int, + SkBlendMode, + const SkPaint&) override; + void onDrawAtlas(const SkImage*, + const SkRSXform[], + const SkRect[], + const SkColor[], + int, + SkBlendMode, + const SkRect*, + const SkPaint*) override; + void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override; + void onDrawPicture(const SkPicture*, + const SkMatrix*, + const SkPaint*) override; + + void onDrawEdgeAAQuad(const SkRect&, + const SkPoint[4], + QuadAAFlags, + const SkColor4f&, + SkBlendMode) override; + void onDrawEdgeAAImageSet(const ImageSetEntry[], + int, + const SkPoint[], + const SkMatrix[], + const SkPaint*, + SrcRectConstraint) override; + + private: + SkNWayCanvas internal_canvas_; +}; + +} // namespace testing +} // namespace flutter + +#endif // TESTING_MOCK_CANVAS_H_ From ce416217b637d0d9f11a911abe39e386afc3efdb Mon Sep 17 00:00:00 2001 From: David Worsham Date: Mon, 11 Nov 2019 14:46:10 -0800 Subject: [PATCH 11/11] Format code --- flow/layers/clip_path_layer.cc | 2 +- flow/layers/clip_rect_layer.cc | 2 +- flow/layers/clip_rrect_layer.cc | 2 +- flow/layers/container_layer.cc | 35 +++-- flow/layers/container_layer.h | 8 +- flow/layers/layer_test.cc | 39 +++-- flow/layers/layer_test.h | 6 +- flow/layers/layer_tree.cc | 4 +- flow/layers/layer_tree.h | 2 +- flow/layers/opacity_layer.cc | 9 +- flow/layers/opacity_layer.h | 2 +- flow/layers/physical_shape_layer.cc | 10 +- flow/layers/physical_shape_layer.h | 3 +- flow/layers/physical_shape_layer_unittests.cc | 61 ++++---- flow/layers/transform_layer.cc | 2 +- flow/scene_update_context.h | 4 +- lib/ui/compositing/scene_builder.h | 1 + lib/ui/compositing/scene_host.h | 7 +- lib/ui/painting/engine_layer.h | 1 + shell/common/shell_test.cc | 5 +- shell/common/shell_test.h | 10 +- testing/mock_canvas.cc | 147 ++++++++++-------- testing/mock_canvas.h | 5 +- 23 files changed, 201 insertions(+), 166 deletions(-) diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index 0db4f6ca4aab4..ed4eb35603968 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -8,7 +8,7 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index 9bccc9e2d870f..6a5ff9f7f92b2 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -8,7 +8,7 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index a2901b5d1034d..4d09ad7526271 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -8,7 +8,7 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index faa4b597ecd1c..0a584d9ad1cb2 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -8,14 +8,14 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { namespace { float ClampElevation(float elevation, - float parent_elevation, - float max_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. @@ -94,17 +94,17 @@ void ContainerLayer::UpdateScene(SceneUpdateContext& context) { #endif // defined(OS_FUCHSIA) ElevatedContainerLayer::ElevatedContainerLayer(float elevation) - : elevation_(elevation), - clamped_elevation_(elevation) {} + : elevation_(elevation), clamped_elevation_(elevation) {} -void ElevatedContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { +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); + clamped_elevation_ = ClampElevation(elevation_, parent_elevation_, + context->frame_physical_depth); context->total_elevation += clamped_elevation_; ContainerLayer::Preroll(context, matrix); @@ -113,12 +113,14 @@ void ElevatedContainerLayer::Preroll(PrerollContext* context, const SkMatrix& ma context->total_elevation = parent_elevation_; } -FuchsiaSystemCompositedContainerLayer::FuchsiaSystemCompositedContainerLayer(SkColor color, SkAlpha opacity, float elevation) - : ElevatedContainerLayer(elevation), - color_(color), - opacity_(opacity) {} +FuchsiaSystemCompositedContainerLayer::FuchsiaSystemCompositedContainerLayer( + SkColor color, + SkAlpha opacity, + float elevation) + : ElevatedContainerLayer(elevation), color_(color), opacity_(opacity) {} -void FuchsiaSystemCompositedContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { +void FuchsiaSystemCompositedContainerLayer::Preroll(PrerollContext* context, + const SkMatrix& matrix) { TRACE_EVENT0("flutter", "SystemCompositedContainerLayer::Preroll"); #if !defined(OS_FUCHSIA) FML_NOTIMPLEMENTED(); @@ -156,7 +158,8 @@ void FuchsiaSystemCompositedContainerLayer::Paint(PaintContext& context) const { #if defined(OS_FUCHSIA) -void FuchsiaSystemCompositedContainerLayer::UpdateScene(SceneUpdateContext& context) { +void FuchsiaSystemCompositedContainerLayer::UpdateScene( + SceneUpdateContext& context) { FML_DCHECK(needs_system_composite()); // Retained rendering: speedup by reusing a retained entity node if @@ -171,8 +174,8 @@ void FuchsiaSystemCompositedContainerLayer::UpdateScene(SceneUpdateContext& cont return; } - SceneUpdateContext::Frame frame(context, rrect_, color_, - opacity_ / 255.0f, elevation(), this); + SceneUpdateContext::Frame frame(context, rrect_, color_, opacity_ / 255.0f, + elevation(), this); // Paint the child layers into the Frame. for (auto& layer : layers()) { if (layer->needs_painting()) { diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index a7456e00fa1c8..2116547d75efd 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -59,7 +59,9 @@ class FuchsiaSystemCompositedContainerLayer : public ElevatedContainerLayer { public: static bool should_system_composite() { return true; } - FuchsiaSystemCompositedContainerLayer(SkColor color, SkAlpha opacity, float elevation); + FuchsiaSystemCompositedContainerLayer(SkColor color, + SkAlpha opacity, + float elevation); ~FuchsiaSystemCompositedContainerLayer() override = default; void Preroll(PrerollContext* context, const SkMatrix& matrix) override; @@ -68,9 +70,7 @@ class FuchsiaSystemCompositedContainerLayer : public ElevatedContainerLayer { #endif // defined(OS_FUCHSIA) void Paint(PaintContext& context) const override; - void set_dimensions(SkRRect rrect) { - rrect_ = rrect; - } + void set_dimensions(SkRRect rrect) { rrect_ = rrect; } SkColor color() const { return color_; } SkAlpha opacity() const { return opacity_; } diff --git a/flow/layers/layer_test.cc b/flow/layers/layer_test.cc index 2a6c16b93d8e4..ef17582b6afe8 100644 --- a/flow/layers/layer_test.cc +++ b/flow/layers/layer_test.cc @@ -11,7 +11,10 @@ namespace flutter { namespace testing { namespace { -PrerollContext CreatePrerollContext(MockCanvas* canvas, Stopwatch& stopwatch, MutatorsStack& mutators_stack, TextureRegistry& texture_registry) { +PrerollContext CreatePrerollContext(MockCanvas* canvas, + Stopwatch& stopwatch, + MutatorsStack& mutators_stack, + TextureRegistry& texture_registry) { return { nullptr, // raster_cache (don't care) nullptr, // gr_context (don't care) @@ -29,25 +32,33 @@ PrerollContext CreatePrerollContext(MockCanvas* canvas, Stopwatch& stopwatch, Mu }; } -Layer::PaintContext CreatePaintContext(MockCanvas* canvas, Stopwatch& stopwatch, TextureRegistry& texture_registry) { +Layer::PaintContext CreatePaintContext(MockCanvas* canvas, + Stopwatch& stopwatch, + TextureRegistry& texture_registry) { return { - canvas->GetInternalCanvas(), // internal_nodes_canvas - canvas, // leaf_nodes_canvas - nullptr, // gr_context (don't care) - nullptr, // view_embedder (don't care) - stopwatch, // raster_time (don't care) - stopwatch, // ui_time (don't care) - texture_registry, // texture_registry (don't care) - nullptr, // raster_cache (don't care) - false, // checkerboard_offscreen_layers - 10000.0f, // frame_physical_depth - 1.0f, // frame_device_pixel_ratio + canvas->GetInternalCanvas(), // internal_nodes_canvas + canvas, // leaf_nodes_canvas + nullptr, // gr_context (don't care) + nullptr, // view_embedder (don't care) + stopwatch, // raster_time (don't care) + stopwatch, // ui_time (don't care) + texture_registry, // texture_registry (don't care) + nullptr, // raster_cache (don't care) + false, // checkerboard_offscreen_layers + 10000.0f, // frame_physical_depth + 1.0f, // frame_device_pixel_ratio }; } } // namespace -LayerTest::LayerTest(MockCanvas* canvas) : preroll_context_(CreatePrerollContext(canvas, stopwatch_, mutators_stack_, texture_registry_)), paint_context_(CreatePaintContext(canvas, stopwatch_, texture_registry_)) {} +LayerTest::LayerTest(MockCanvas* canvas) + : preroll_context_(CreatePrerollContext(canvas, + stopwatch_, + mutators_stack_, + texture_registry_)), + paint_context_( + CreatePaintContext(canvas, stopwatch_, texture_registry_)) {} } // namespace testing } // namespace flutter diff --git a/flow/layers/layer_test.h b/flow/layers/layer_test.h index 15a4bb3e03fc7..f0362afcfe104 100644 --- a/flow/layers/layer_test.h +++ b/flow/layers/layer_test.h @@ -5,17 +5,17 @@ #ifndef TESTING_LAYER_TEST_H_ #define TESTING_LAYER_TEST_H_ -#include "gtest/gtest.h" #include "flutter/flow/layers/layer.h" #include "flutter/testing/mock_canvas.h" +#include "gtest/gtest.h" namespace flutter { namespace testing { class LayerTest : public ::testing::Test { public: - LayerTest(MockCanvas* canvas); - virtual ~LayerTest() = default; + LayerTest(MockCanvas* canvas); + virtual ~LayerTest() = default; PrerollContext* preroll_context() { return &preroll_context_; } Layer::PaintContext& paint_context() { return paint_context_; } diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index fab545e7ac371..17584ea269775 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -11,7 +11,7 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { @@ -62,7 +62,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, // Ensure the context is aware of the view metrics. context.set_dimensions(frame_size_, frame_physical_depth_, - frame_device_pixel_ratio_); + frame_device_pixel_ratio_); const auto& metrics = context.metrics(); FML_DCHECK(metrics->scale_x > 0.0f); diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index d84a457a74140..eb0541e54d2ab 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -16,7 +16,7 @@ #include "third_party/skia/include/core/SkPicture.h" namespace scenic { - class ContainerNode; +class ContainerNode; } namespace flutter { diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index e303b8fdb7412..debc42cd1f6bc 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -9,14 +9,15 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.001f; #if !defined(OS_FUCHSIA) -void OpacityLayerBase::Preroll(PrerollContext* context, const SkMatrix& matrix) { +void OpacityLayerBase::Preroll(PrerollContext* context, + const SkMatrix& matrix) { const SkAlpha alpha = SkColorGetA(color()); const float parent_is_opaque = context->is_opaque; @@ -29,7 +30,9 @@ void OpacityLayerBase::Preroll(PrerollContext* context, const SkMatrix& matrix) #endif OpacityLayer::OpacityLayer(SkAlpha opacity, const SkPoint& offset) - : OpacityLayerBase(SK_ColorBLACK, opacity, kOpacityElevationWhenUsingSystemCompositor), + : OpacityLayerBase(SK_ColorBLACK, + opacity, + kOpacityElevationWhenUsingSystemCompositor), offset_(offset) { // Ensure OpacityLayer has only one direct child. // diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index d28a13a3d7de6..6a155ade836ef 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -19,7 +19,7 @@ class OpacityLayerBase : public ContainerLayer { static bool should_system_composite() { return false; } OpacityLayerBase(SkColor color, SkAlpha opacity, float elevation) - : color_(color), opacity_(opacity) {} + : color_(color), opacity_(opacity) {} void Preroll(PrerollContext* context, const SkMatrix& matrix) override; diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 728ac41879b86..8b13ae06fd199 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -10,7 +10,7 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { @@ -108,9 +108,13 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context, // t = tangent of AOB, i.e., multiplier for elevation to extent SkRect bounds(paint_bounds()); // tangent for x - double tx = (kLightRadius * context->frame_device_pixel_ratio + bounds.width() * 0.5) / kLightHeight; + double tx = (kLightRadius * context->frame_device_pixel_ratio + + bounds.width() * 0.5) / + kLightHeight; // tangent for y - double ty = (kLightRadius * context->frame_device_pixel_ratio + bounds.height() * 0.5) / kLightHeight; + double ty = (kLightRadius * context->frame_device_pixel_ratio + + bounds.height() * 0.5) / + kLightHeight; bounds.outset(elevation() * tx, elevation() * ty); set_paint_bounds(bounds); } diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index 22b27cff19e12..97e597692df7b 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -18,8 +18,7 @@ class PhysicalShapeLayerBase : public ElevatedContainerLayer { static bool should_system_composite() { return false; } PhysicalShapeLayerBase(SkColor color, SkAlpha opacity, float elevation) - : ElevatedContainerLayer(elevation), - color_(color) {} + : ElevatedContainerLayer(elevation), color_(color) {} void set_dimensions(SkRRect rrect) {} diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index 2efd1e576e830..ffdad8e14e5fd 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -21,7 +21,8 @@ class PhysicalShapeLayerTestMockCanvas : public testing::MockCanvas { const SkDrawShadowRec& rec; }; - PhysicalShapeLayerTestMockCanvas(int width, int height) : testing::MockCanvas(width, height) {} + PhysicalShapeLayerTestMockCanvas(int width, int height) + : testing::MockCanvas(width, height) {} const std::vector path_draw_calls() const { return path_draw_calls_; @@ -34,7 +35,8 @@ class PhysicalShapeLayerTestMockCanvas : public testing::MockCanvas { void onDrawPath(const SkPath& path, const SkPaint& paint) override { path_draw_calls_.emplace_back(PathDrawCall({path, paint})); } - void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override { + void onDrawShadowRec(const SkPath& path, + const SkDrawShadowRec& rec) override { shadow_draw_calls_.emplace_back(ShadowRecDrawCall({path, rec})); } @@ -51,10 +53,10 @@ class PhysicalShapeLayerTest : public testing::LayerTest { }; TEST_F(PhysicalShapeLayerTest, EmptyLayer) { - auto layer = std::make_shared(SK_ColorGREEN, - SK_ColorBLACK, - 0.0f, // elevation - SkPath(), Clip::none); + auto layer = + std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 0.0f, // elevation + SkPath(), Clip::none); layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); @@ -68,10 +70,10 @@ TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) { SkPath layer_path; layer_path.addRect(0, 8, 8, 0).close(); - auto layer = std::make_shared(SK_ColorGREEN, SK_ColorBLACK, - 0.0f, // elevation - layer_path, - Clip::none); + auto layer = + std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 0.0f, // elevation + layer_path, Clip::none); layer->Preroll(&preroll_context_, SkMatrix()); EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds()); EXPECT_TRUE(layer->needs_painting()); @@ -91,21 +93,17 @@ TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPath) { layer_path.addRect(0, 8, 8, 0).close(); child1_path.addRect(4, 12, 12, 0).close(); child2_path.addRect(3, 15, 5, 2).close(); - auto child1 = std::make_shared(SK_ColorRED, - SK_ColorBLACK, + auto child1 = std::make_shared(SK_ColorRED, SK_ColorBLACK, 0.0f, // elevation - child1_path, - Clip::none); - auto child2 = std::make_shared(SK_ColorBLUE, - SK_ColorBLACK, - 0.0f, // elevation - child2_path, - Clip::none); - auto layer = std::make_shared(SK_ColorGREEN, - SK_ColorBLACK, - 0.0f, // elevation - layer_path, - Clip::none); + child1_path, Clip::none); + auto child2 = + std::make_shared(SK_ColorBLUE, SK_ColorBLACK, + 0.0f, // elevation + child2_path, Clip::none); + auto layer = + std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 0.0f, // elevation + layer_path, Clip::none); layer->Add(child1); layer->Add(child2); @@ -131,18 +129,19 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) { SkPath layer_path; layer_path.addRect(0, 8, 8, 0).close(); - auto layer = std::make_shared(SK_ColorGREEN, SK_ColorBLACK, - 20.0f, // elevation - layer_path, - Clip::none); + auto layer = + std::make_shared(SK_ColorGREEN, SK_ColorBLACK, + 20.0f, // elevation + layer_path, Clip::none); - preroll_context()->frame_physical_depth = 10.0f; // Clamp depth + preroll_context()->frame_physical_depth = 10.0f; // Clamp depth layer->Preroll(preroll_context(), SkMatrix()); EXPECT_NE(layer->paint_bounds(), layer_path.getBounds()); EXPECT_EQ(layer->elevation(), 10.0f); EXPECT_EQ(layer->total_elevation(), 10.0f); EXPECT_TRUE(layer->needs_painting()); - EXPECT_EQ(layer->needs_system_composite(), PhysicalShapeLayerBase::should_system_composite()); + EXPECT_EQ(layer->needs_system_composite(), + PhysicalShapeLayerBase::should_system_composite()); layer->Paint(paint_context()); EXPECT_EQ(canvas_.path_draw_calls().size(), 1u); @@ -175,7 +174,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) { layers[0]->Add(layers[2]); layers[2]->Add(layers[3]); - preroll_context()->frame_physical_depth = 6.0f; // Clamp depth + preroll_context()->frame_physical_depth = 6.0f; // Clamp depth layers[0]->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layers[0]->elevation(), 1.0f); EXPECT_EQ(layers[1]->elevation(), 2.0f); diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 4cb05bdaf6b85..288b95a6e7e45 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -8,7 +8,7 @@ #if defined(OS_FUCHSIA) #include "flutter/flow/scene_update_context.h" //nogncheck -#endif // defined(OS_FUCHSIA) +#endif // defined(OS_FUCHSIA) namespace flutter { diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index 2f617667ddc30..05e6744d5cfb8 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -147,8 +147,8 @@ class SceneUpdateContext { const fuchsia::ui::gfx::MetricsPtr& metrics() const { return metrics_; } void set_dimensions(const SkISize& frame_physical_size, - float frame_physical_depth, - float frame_device_pixel_ratio) { + float frame_physical_depth, + float frame_device_pixel_ratio) { frame_physical_size_ = frame_physical_size; frame_physical_depth_ = frame_physical_depth; frame_device_pixel_ratio_ = frame_device_pixel_ratio; diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index 9f4dbd5d44e33..7176b781a15b8 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -29,6 +29,7 @@ class SceneHost; class SceneBuilder : public RefCountedDartWrappable { DEFINE_WRAPPERTYPEINFO(); FML_FRIEND_MAKE_REF_COUNTED(SceneBuilder); + public: static void RegisterNatives(tonic::DartLibraryNatives* natives); static fml::RefPtr Create(); diff --git a/lib/ui/compositing/scene_host.h b/lib/ui/compositing/scene_host.h index 8d45683859b9d..b2b29e0536ad7 100644 --- a/lib/ui/compositing/scene_host.h +++ b/lib/ui/compositing/scene_host.h @@ -20,6 +20,7 @@ namespace flutter { class SceneHost : public RefCountedDartWrappable { DEFINE_WRAPPERTYPEINFO(); + public: static void RegisterNatives(tonic::DartLibraryNatives* natives); static fml::RefPtr Create( @@ -32,9 +33,9 @@ class SceneHost : public RefCountedDartWrappable { static void OnViewStateChanged(scenic::ResourceId id, bool state); SceneHost(fml::RefPtr viewHolderToken, - Dart_Handle viewConnectedCallback, - Dart_Handle viewDisconnectedCallback, - Dart_Handle viewStateChangedCallback); + Dart_Handle viewConnectedCallback, + Dart_Handle viewDisconnectedCallback, + Dart_Handle viewStateChangedCallback); ~SceneHost() override; zx_koid_t id() const { return koid_; } diff --git a/lib/ui/painting/engine_layer.h b/lib/ui/painting/engine_layer.h index 41d1c669e3c2c..b41414a9efe84 100644 --- a/lib/ui/painting/engine_layer.h +++ b/lib/ui/painting/engine_layer.h @@ -20,6 +20,7 @@ class EngineLayer; class EngineLayer : public RefCountedDartWrappable { DEFINE_WRAPPERTYPEINFO(); FML_FRIEND_MAKE_REF_COUNTED(EngineLayer); + public: static void RegisterNatives(tonic::DartLibraryNatives* natives); static fml::RefPtr Create(std::shared_ptr layer); diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index 24de6b16c9949..02ebd38d4cce3 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -139,7 +139,10 @@ void ShellTest::PumpOneFrame(Shell* shell, double width, double height, LayerTreeBuilder builder) { - PumpOneFrame(shell, flutter::ViewportMetrics {1, width, height, flutter::kUnsetDepth, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, std::move(builder)); + PumpOneFrame(shell, + flutter::ViewportMetrics{1, width, height, flutter::kUnsetDepth, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + std::move(builder)); } void ShellTest::PumpOneFrame(Shell* shell, diff --git a/shell/common/shell_test.h b/shell/common/shell_test.h index d52907804d447..5679226159dd2 100644 --- a/shell/common/shell_test.h +++ b/shell/common/shell_test.h @@ -57,10 +57,12 @@ class ShellTest : public ThreadTest { using LayerTreeBuilder = std::function root)>; static void PumpOneFrame(Shell* shell, - double width = 1, - double height = 1, - LayerTreeBuilder = {}); - static void PumpOneFrame(Shell* shell, flutter::ViewportMetrics viewport_metrics, LayerTreeBuilder = {}); + double width = 1, + double height = 1, + LayerTreeBuilder = {}); + static void PumpOneFrame(Shell* shell, + flutter::ViewportMetrics viewport_metrics, + LayerTreeBuilder = {}); static void DispatchFakePointerData(Shell* shell); // Declare |UnreportedTimingsCount|, |GetNeedsReportTimings| and diff --git a/testing/mock_canvas.cc b/testing/mock_canvas.cc index 0e79cb5e81f03..805537aeea1c7 100644 --- a/testing/mock_canvas.cc +++ b/testing/mock_canvas.cc @@ -14,7 +14,8 @@ MockCanvas::MockCanvas(int width, int height) : SkCanvasVirtualEnforcer(width, height), internal_canvas_(imageInfo().width(), imageInfo().height()) {} -SkCanvas::SaveLayerStrategy MockCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { +SkCanvas::SaveLayerStrategy MockCanvas::getSaveLayerStrategy( + const SaveLayerRec& rec) { (void)SkCanvasVirtualEnforcer::getSaveLayerStrategy(rec); return kNoLayer_SaveLayerStrategy; } @@ -34,132 +35,142 @@ void MockCanvas::onDrawDrawable(SkDrawable*, const SkMatrix*) { FML_DCHECK(false); } void MockCanvas::onDrawTextBlob(const SkTextBlob*, - SkScalar, - SkScalar, - const SkPaint&) { + SkScalar, + SkScalar, + const SkPaint&) { FML_DCHECK(false); } void MockCanvas::onDrawPatch(const SkPoint[12], - const SkColor[4], - const SkPoint[4], - SkBlendMode, - const SkPaint&) { + const SkColor[4], + const SkPoint[4], + SkBlendMode, + const SkPaint&) { FML_DCHECK(false); } -void MockCanvas::onDrawPaint(const SkPaint&) { FML_DCHECK(false); } -void MockCanvas::onDrawBehind(const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawPaint(const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawBehind(const SkPaint&) { + FML_DCHECK(false); +} void MockCanvas::onDrawPoints(PointMode, - size_t, - const SkPoint[], - const SkPaint&) { + size_t, + const SkPoint[], + const SkPaint&) { + FML_DCHECK(false); +} +void MockCanvas::onDrawRect(const SkRect&, const SkPaint&) { FML_DCHECK(false); } -void MockCanvas::onDrawRect(const SkRect&, const SkPaint&) { FML_DCHECK(false); } void MockCanvas::onDrawRegion(const SkRegion&, const SkPaint&) { FML_DCHECK(false); } -void MockCanvas::onDrawOval(const SkRect&, const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawOval(const SkRect&, const SkPaint&) { + FML_DCHECK(false); +} void MockCanvas::onDrawArc(const SkRect&, - SkScalar, - SkScalar, - bool, - const SkPaint&) { + SkScalar, + SkScalar, + bool, + const SkPaint&) { FML_DCHECK(false); } void MockCanvas::onDrawRRect(const SkRRect&, const SkPaint&) { FML_DCHECK(false); } -void MockCanvas::onDrawPath(const SkPath&, const SkPaint&) { FML_DCHECK(false); } +void MockCanvas::onDrawPath(const SkPath&, const SkPaint&) { + FML_DCHECK(false); +} void MockCanvas::onDrawBitmap(const SkBitmap&, - SkScalar, - SkScalar, - const SkPaint*) { + SkScalar, + SkScalar, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawBitmapRect(const SkBitmap&, - const SkRect*, - const SkRect&, - const SkPaint*, - SrcRectConstraint) { + const SkRect*, + const SkRect&, + const SkPaint*, + SrcRectConstraint) { FML_DCHECK(false); } void MockCanvas::onDrawImage(const SkImage*, - SkScalar, - SkScalar, - const SkPaint*) { + SkScalar, + SkScalar, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawImageRect(const SkImage*, - const SkRect*, - const SkRect&, - const SkPaint*, - SrcRectConstraint) { + const SkRect*, + const SkRect&, + const SkPaint*, + SrcRectConstraint) { FML_DCHECK(false); } void MockCanvas::onDrawImageNine(const SkImage*, - const SkIRect&, - const SkRect&, - const SkPaint*) { + const SkIRect&, + const SkRect&, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawBitmapNine(const SkBitmap&, - const SkIRect&, - const SkRect&, - const SkPaint*) { + const SkIRect&, + const SkRect&, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawImageLattice(const SkImage*, - const Lattice&, - const SkRect&, - const SkPaint*) { + const Lattice&, + const SkRect&, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawBitmapLattice(const SkBitmap&, - const Lattice&, - const SkRect&, - const SkPaint*) { + const Lattice&, + const SkRect&, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawVerticesObject(const SkVertices*, - const SkVertices::Bone[], - int, - SkBlendMode, - const SkPaint&) { + const SkVertices::Bone[], + int, + SkBlendMode, + const SkPaint&) { FML_DCHECK(false); } void MockCanvas::onDrawAtlas(const SkImage*, - const SkRSXform[], - const SkRect[], - const SkColor[], - int, - SkBlendMode, - const SkRect*, - const SkPaint*) { + const SkRSXform[], + const SkRect[], + const SkColor[], + int, + SkBlendMode, + const SkRect*, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) { FML_DCHECK(false); } void MockCanvas::onDrawPicture(const SkPicture*, - const SkMatrix*, - const SkPaint*) { + const SkMatrix*, + const SkPaint*) { FML_DCHECK(false); } void MockCanvas::onDrawEdgeAAQuad(const SkRect&, - const SkPoint[4], - QuadAAFlags, - const SkColor4f&, - SkBlendMode) { + const SkPoint[4], + QuadAAFlags, + const SkColor4f&, + SkBlendMode) { FML_DCHECK(false); } void MockCanvas::onDrawEdgeAAImageSet(const ImageSetEntry[], - int, - const SkPoint[], - const SkMatrix[], - const SkPaint*, - SrcRectConstraint) { + int, + const SkPoint[], + const SkMatrix[], + const SkPaint*, + SrcRectConstraint) { FML_DCHECK(false); } diff --git a/testing/mock_canvas.h b/testing/mock_canvas.h index 58fb1cf23ce89..c2db164ee53f1 100644 --- a/testing/mock_canvas.h +++ b/testing/mock_canvas.h @@ -62,10 +62,7 @@ class MockCanvas : public SkCanvasVirtualEnforcer { const SkRect&, const SkPaint*, SrcRectConstraint) override; - void onDrawImage(const SkImage*, - SkScalar, - SkScalar, - const SkPaint*) override; + void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override; void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&,