diff --git a/content_handler/rasterizer.cc b/content_handler/rasterizer.cc index f98ece99b5a..17dc6f75112 100644 --- a/content_handler/rasterizer.cc +++ b/content_handler/rasterizer.cc @@ -12,11 +12,6 @@ namespace flutter_runner { -namespace { -constexpr uint32_t kContentImageResourceId = 1; -constexpr uint32_t kRootNodeId = mozart::kSceneRootNodeId; -} // namespace - Rasterizer::Rasterizer() {} Rasterizer::~Rasterizer() {} @@ -35,10 +30,14 @@ void Rasterizer::Draw(std::unique_ptr layer_tree, } const SkISize& frame_size = layer_tree->frame_size(); + auto update = mozart::SceneUpdate::New(); + // TODO(abarth): Support incremental updates. + update->clear_resources = true; + update->clear_nodes = true; if (frame_size.isEmpty()) { - update->nodes.insert(kRootNodeId, mozart::Node::New()); + update->nodes.insert(mozart::kSceneRootNodeId, mozart::Node::New()); // Publish the updated scene contents. // TODO(jeffbrown): We should set the metadata's presentation_time here too. scene_->Update(std::move(update)); @@ -49,39 +48,15 @@ void Rasterizer::Draw(std::unique_ptr layer_tree, return; } - // Get a surface to draw the contents. - mozart::ImagePtr image; - sk_sp surface = - mozart::MakeSkSurface(frame_size, buffer_producer_.get(), &image); - - FTL_CHECK(surface); - flow::CompositorContext::ScopedFrame frame = - compositor_context_.AcquireFrame(nullptr, *surface->getCanvas()); + compositor_context_.AcquireFrame(nullptr, nullptr); layer_tree->Preroll(frame); - // Update the scene contents. - mozart::RectF bounds; - bounds.width = frame_size.width(); - bounds.height = frame_size.height(); - - auto content_resource = mozart::Resource::New(); - content_resource->set_image(mozart::ImageResource::New()); - content_resource->get_image()->image = std::move(image); - update->resources.insert(kContentImageResourceId, - std::move(content_resource)); - + flow::SceneUpdateContext context(update.get(), buffer_producer_.get()); auto root_node = mozart::Node::New(); - root_node->hit_test_behavior = mozart::HitTestBehavior::New(); - root_node->op = mozart::NodeOp::New(); - root_node->op->set_image(mozart::ImageNodeOp::New()); - root_node->op->get_image()->content_rect = bounds.Clone(); - root_node->op->get_image()->image_resource_id = kContentImageResourceId; - - layer_tree->UpdateScene(update.get(), root_node.get()); - - update->nodes.insert(kRootNodeId, std::move(root_node)); + layer_tree->UpdateScene(context, root_node.get()); + update->nodes.insert(mozart::kSceneRootNodeId, std::move(root_node)); // Publish the updated scene contents. // TODO(jeffbrown): We should set the metadata's presentation_time here too. @@ -94,10 +69,7 @@ void Rasterizer::Draw(std::unique_ptr layer_tree, // We do this after publishing to take advantage of pipelining. // The image buffer's fence is signalled automatically when the surface // goes out of scope. - SkCanvas* canvas = surface->getCanvas(); - canvas->clear(SK_ColorBLACK); - layer_tree->Paint(frame); - canvas->flush(); + context.ExecutePaintTasks(frame); callback(); } diff --git a/flow/BUILD.gn b/flow/BUILD.gn index 03057da4417..c2c1d06ab6e 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -4,6 +4,8 @@ source_set("flow") { sources = [ + "bitmap_image.cc", + "bitmap_image.h", "compositor_context.cc", "compositor_context.h", "instrumentation.cc", @@ -36,8 +38,8 @@ source_set("flow") { "layers/transform_layer.h", "raster_cache.cc", "raster_cache.h", - "bitmap_image.cc", - "bitmap_image.h", + "scene_update_context.cc", + "scene_update_context.h", "texture_image.h", ] @@ -57,6 +59,7 @@ source_set("flow") { "texture_image_none.cc", ] public_deps = [ + "//apps/mozart/lib/skia", "//apps/mozart/services/composition", ] } else { diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index 91d2f8a8023..b5b1c2daf3b 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -30,18 +30,18 @@ void CompositorContext::EndFrame(ScopedFrame& frame, CompositorContext::ScopedFrame CompositorContext::AcquireFrame( GrContext* gr_context, - SkCanvas& canvas, + SkCanvas* canvas, bool instrumentation_enabled) { return ScopedFrame(*this, gr_context, canvas, instrumentation_enabled); } CompositorContext::ScopedFrame::ScopedFrame(CompositorContext& context, GrContext* gr_context, - SkCanvas& canvas, + SkCanvas* canvas, bool instrumentation_enabled) : context_(context), gr_context_(gr_context), - canvas_(&canvas), + canvas_(canvas), instrumentation_enabled_(instrumentation_enabled) { context_.BeginFrame(*this, instrumentation_enabled_); } diff --git a/flow/compositor_context.h b/flow/compositor_context.h index f16f3c46029..a981f75847b 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -38,7 +38,7 @@ class CompositorContext { ScopedFrame(CompositorContext& context, GrContext* gr_context, - SkCanvas& canvas, + SkCanvas* canvas, bool instrumentation_enabled); friend class CompositorContext; @@ -51,7 +51,7 @@ class CompositorContext { ~CompositorContext(); ScopedFrame AcquireFrame(GrContext* gr_context, - SkCanvas& canvas, + SkCanvas* canvas, bool instrumentation_enabled = true); void OnGrContextDestroyed(); diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 1f0233c878e..aedff4172b4 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -4,72 +4,47 @@ #include "flutter/flow/layers/child_scene_layer.h" +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/nodes.fidl.h" + namespace flow { -namespace { - -mozart::TransformPtr GetTransformFromSkMatrix(const SkMatrix& input) { - // Expand 3x3 to 4x4. - auto output = mozart::Transform::New(); - output->matrix.resize(16u); - output->matrix[0] = input[0]; - output->matrix[1] = input[1]; - output->matrix[2] = 0.f; - output->matrix[3] = input[2]; - output->matrix[4] = input[3]; - output->matrix[5] = input[4]; - output->matrix[6] = 0.f; - output->matrix[7] = input[5]; - output->matrix[8] = 0.f; - output->matrix[9] = 0.f; - output->matrix[10] = 1.f; - output->matrix[11] = 0.f; - output->matrix[12] = input[6]; - output->matrix[13] = input[7]; - output->matrix[14] = 0.f; - output->matrix[15] = input[8]; - return output; -} - -// TODO(abarth): We need to figure out how to allocate these ids sensibly. -static uint32_t next_id = 10; - -} // namespace ChildSceneLayer::ChildSceneLayer() : device_pixel_ratio_(1.0f) {} ChildSceneLayer::~ChildSceneLayer() {} void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { - transform_ = matrix; + set_needs_system_composite(true); + transform_.setIdentity(); transform_.preTranslate(offset_.x(), offset_.y()); float inverse_device_pixel_ratio = 1.f / device_pixel_ratio_; transform_.preScale(inverse_device_pixel_ratio, inverse_device_pixel_ratio); } void ChildSceneLayer::Paint(PaintContext& context) { - TRACE_EVENT0("flutter", "ChildSceneLayer::Paint"); + FTL_DCHECK(false) << "Failed to composite child scene."; } -void ChildSceneLayer::UpdateScene(mozart::SceneUpdate* update, +void ChildSceneLayer::UpdateScene(SceneUpdateContext& context, mozart::Node* container) { - uint32_t id = next_id++; + FTL_DCHECK(needs_system_composite()); - auto child_resource = mozart::Resource::New(); - child_resource->set_scene(mozart::SceneResource::New()); - child_resource->get_scene()->scene_token = mozart::SceneToken::New(); - child_resource->get_scene()->scene_token->value = scene_token_; - update->resources.insert(id, std::move(child_resource)); + auto resource = mozart::Resource::New(); + resource->set_scene(mozart::SceneResource::New()); + resource->get_scene()->scene_token = mozart::SceneToken::New(); + resource->get_scene()->scene_token->value = scene_token_; - auto child_node = mozart::Node::New(); - child_node->op = mozart::NodeOp::New(); - child_node->op->set_scene(mozart::SceneNodeOp::New()); - child_node->op->get_scene()->scene_resource_id = id; - child_node->content_clip = mozart::RectF::New(); - child_node->content_clip->width = physical_size_.width(); - child_node->content_clip->height = physical_size_.height(); - child_node->content_transform = GetTransformFromSkMatrix(transform_); - update->nodes.insert(id, std::move(child_node)); - container->child_node_ids.push_back(id); + auto node = mozart::Node::New(); + node->op = mozart::NodeOp::New(); + node->op->set_scene(mozart::SceneNodeOp::New()); + node->op->get_scene()->scene_resource_id = + context.AddResource(std::move(resource)); + node->content_clip = mozart::RectF::New(); + node->content_clip->width = physical_size_.width(); + node->content_clip->height = physical_size_.height(); + node->content_transform = mozart::Transform::From(transform_); + + context.AddChildNode(container, std::move(node)); } } // namespace flow diff --git a/flow/layers/child_scene_layer.h b/flow/layers/child_scene_layer.h index 649a2a83661..ffd18b2a0ef 100644 --- a/flow/layers/child_scene_layer.h +++ b/flow/layers/child_scene_layer.h @@ -29,7 +29,7 @@ class ChildSceneLayer : public Layer { void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) override; - void UpdateScene(mozart::SceneUpdate* update, + void UpdateScene(SceneUpdateContext& context, mozart::Node* container) override; private: diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index ae63e38bc1b..693e568bcf3 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -4,6 +4,11 @@ #include "flutter/flow/layers/clip_path_layer.h" +#if defined(OS_FUCHSIA) +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/nodes.fidl.h" +#endif // defined(OS_FUCHSIA) + namespace flow { ClipPathLayer::ClipPathLayer() {} @@ -17,8 +22,21 @@ void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { set_paint_bounds(context->child_paint_bounds); } +#if defined(OS_FUCHSIA) + +void ClipPathLayer::UpdateScene(SceneUpdateContext& context, + mozart::Node* container) { + auto node = mozart::Node::New(); + node->content_clip = mozart::RectF::From(clip_path_.getBounds()); + UpdateSceneChildrenInsideNode(context, container, std::move(node)); +} + +#endif // defined(OS_FUCHSIA) + void ClipPathLayer::Paint(PaintContext& context) { TRACE_EVENT0("flutter", "ClipPathLayer::Paint"); + FTL_DCHECK(!needs_system_composite()); + SkAutoCanvasRestore save(&context.canvas, false); context.canvas.saveLayer(&paint_bounds(), nullptr); context.canvas.clipPath(clip_path_, true); diff --git a/flow/layers/clip_path_layer.h b/flow/layers/clip_path_layer.h index 185f8b7be5c..a62d66aa42a 100644 --- a/flow/layers/clip_path_layer.h +++ b/flow/layers/clip_path_layer.h @@ -20,6 +20,11 @@ class ClipPathLayer : public ContainerLayer { void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) override; +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context, + mozart::Node* container) override; +#endif // defined(OS_FUCHSIA) + private: SkPath clip_path_; diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index 66db9c7d080..411b843d506 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -4,6 +4,11 @@ #include "flutter/flow/layers/clip_rect_layer.h" +#if defined(OS_FUCHSIA) +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/nodes.fidl.h" +#endif // defined(OS_FUCHSIA) + namespace flow { ClipRectLayer::ClipRectLayer() {} @@ -17,8 +22,21 @@ void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { set_paint_bounds(context->child_paint_bounds); } +#if defined(OS_FUCHSIA) + +void ClipRectLayer::UpdateScene(SceneUpdateContext& context, + mozart::Node* container) { + auto node = mozart::Node::New(); + node->content_clip = mozart::RectF::From(clip_rect_); + UpdateSceneChildrenInsideNode(context, container, std::move(node)); +} + +#endif // defined(OS_FUCHSIA) + void ClipRectLayer::Paint(PaintContext& context) { TRACE_EVENT0("flutter", "ClipRectLayer::Paint"); + FTL_DCHECK(!needs_system_composite()); + SkAutoCanvasRestore save(&context.canvas, true); context.canvas.clipRect(paint_bounds()); PaintChildren(context); diff --git a/flow/layers/clip_rect_layer.h b/flow/layers/clip_rect_layer.h index 64d7dc43525..5b09e006366 100644 --- a/flow/layers/clip_rect_layer.h +++ b/flow/layers/clip_rect_layer.h @@ -20,6 +20,11 @@ class ClipRectLayer : public ContainerLayer { void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) override; +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context, + mozart::Node* container) override; +#endif // defined(OS_FUCHSIA) + private: SkRect clip_rect_; diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 9f8f567303e..66aa9a465b7 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -4,6 +4,11 @@ #include "flutter/flow/layers/clip_rrect_layer.h" +#if defined(OS_FUCHSIA) +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/nodes.fidl.h" +#endif // defined(OS_FUCHSIA) + namespace flow { ClipRRectLayer::ClipRRectLayer() {} @@ -17,8 +22,21 @@ void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { set_paint_bounds(context->child_paint_bounds); } +#if defined(OS_FUCHSIA) + +void ClipRRectLayer::UpdateScene(SceneUpdateContext& context, + mozart::Node* container) { + auto node = mozart::Node::New(); + node->content_clip = mozart::RectF::From(clip_rrect_.getBounds()); + UpdateSceneChildrenInsideNode(context, container, std::move(node)); +} + +#endif // defined(OS_FUCHSIA) + void ClipRRectLayer::Paint(PaintContext& context) { TRACE_EVENT0("flutter", "ClipRRectLayer::Paint"); + FTL_DCHECK(!needs_system_composite()); + SkAutoCanvasRestore save(&context.canvas, false); context.canvas.saveLayer(&paint_bounds(), nullptr); context.canvas.clipRRect(clip_rrect_, true); diff --git a/flow/layers/clip_rrect_layer.h b/flow/layers/clip_rrect_layer.h index 5dc4d8959d4..79b8ae554cb 100644 --- a/flow/layers/clip_rrect_layer.h +++ b/flow/layers/clip_rrect_layer.h @@ -20,6 +20,11 @@ class ClipRRectLayer : public ContainerLayer { void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) override; +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context, + mozart::Node* container) override; +#endif // defined(OS_FUCHSIA) + private: SkRRect clip_rrect_; diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index d2da8a5de83..27507e9ed79 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -6,7 +6,9 @@ namespace flow { -ContainerLayer::ContainerLayer() {} +ContainerLayer::ContainerLayer() { + ctm_.setIdentity(); +} ContainerLayer::~ContainerLayer() {} @@ -27,12 +29,18 @@ void ContainerLayer::PrerollChildren(PrerollContext* context, for (auto& layer : layers_) { PrerollContext child_context = *context; layer->Preroll(&child_context, matrix); + if (layer->needs_system_composite()) + set_needs_system_composite(true); child_paint_bounds.join(child_context.child_paint_bounds); } context->child_paint_bounds = child_paint_bounds; + + if (needs_system_composite()) + ctm_ = matrix; } void ContainerLayer::PaintChildren(PaintContext& context) const { + FTL_DCHECK(!needs_system_composite()); // Intentionally not tracing here as there should be no self-time // and the trace event on this common function has a small overhead. for (auto& layer : layers_) @@ -40,11 +48,34 @@ void ContainerLayer::PaintChildren(PaintContext& context) const { } #if defined(OS_FUCHSIA) -void ContainerLayer::UpdateScene(mozart::SceneUpdate* update, + +void ContainerLayer::UpdateScene(SceneUpdateContext& context, mozart::Node* container) { - for (auto& layer : layers_) - layer->UpdateScene(update, container); + UpdateSceneChildren(context, container); } -#endif + +void ContainerLayer::UpdateSceneChildrenInsideNode(SceneUpdateContext& context, + mozart::Node* container, + mozart::NodePtr node) { + FTL_DCHECK(needs_system_composite()); + UpdateSceneChildren(context, node.get()); + context.FinalizeCurrentPaintTaskIfNeeded(node.get(), ctm()); + context.AddChildNode(container, std::move(node)); +} + +void ContainerLayer::UpdateSceneChildren(SceneUpdateContext& context, + mozart::Node* container) { + FTL_DCHECK(needs_system_composite()); + for (auto& layer : layers_) { + if (layer->needs_system_composite()) { + context.FinalizeCurrentPaintTaskIfNeeded(container, ctm()); + layer->UpdateScene(context, container); + } else { + context.AddLayerToCurrentPaintTask(layer.get()); + } + } +} + +#endif // defined(OS_FUCHSIA) } // namespace flow diff --git a/flow/layers/container_layer.h b/flow/layers/container_layer.h index 4eedf389ec6..0aaa0d64255 100644 --- a/flow/layers/container_layer.h +++ b/flow/layers/container_layer.h @@ -23,15 +23,26 @@ class ContainerLayer : public Layer { void PaintChildren(PaintContext& context) const; #if defined(OS_FUCHSIA) - void UpdateScene(mozart::SceneUpdate* update, + void UpdateScene(SceneUpdateContext& context, mozart::Node* container) override; -#endif + void UpdateSceneChildrenInsideNode(SceneUpdateContext& context, + mozart::Node* container, + mozart::NodePtr node); + void UpdateSceneChildren(SceneUpdateContext& context, + mozart::Node* container); +#endif // defined(OS_FUCHSIA) const std::vector>& layers() const { return layers_; } + protected: + // Valid only after preroll when needs_system_composite() is true. + const SkMatrix& ctm() const { return ctm_; } + private: std::vector> layers_; + SkMatrix ctm_; + FTL_DISALLOW_COPY_AND_ASSIGN(ContainerLayer); }; diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index ef9ed6de3ff..d2e0d564f41 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -8,14 +8,20 @@ namespace flow { -Layer::Layer() : parent_(nullptr), has_paint_bounds_(false), paint_bounds_() {} +Layer::Layer() + : parent_(nullptr), + needs_system_composite_(false), + has_paint_bounds_(false), + paint_bounds_() {} -Layer::~Layer() {} +Layer::~Layer() = default; -void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {} +void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + set_paint_bounds(SkRect::MakeEmpty()); +} #if defined(OS_FUCHSIA) -void Layer::UpdateScene(mozart::SceneUpdate* update, mozart::Node* container) {} +void Layer::UpdateScene(SceneUpdateContext& context, mozart::Node* container) {} #endif } // namespace flow diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 52515d26c39..f55320d24ef 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -10,6 +10,7 @@ #include "flutter/flow/instrumentation.h" #include "flutter/flow/raster_cache.h" +#include "flutter/flow/scene_update_context.h" #include "flutter/glue/trace_event.h" #include "lib/ftl/build_config.h" #include "lib/ftl/logging.h" @@ -24,16 +25,9 @@ #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkXfermode.h" -#if defined(OS_FUCHSIA) -namespace mozart { -class SceneUpdate; -class Node; -} // namespace mozart -#endif - namespace flow { - class ContainerLayer; + class Layer { public: Layer(); @@ -56,7 +50,7 @@ class Layer { virtual void Paint(PaintContext& context) = 0; #if defined(OS_FUCHSIA) - virtual void UpdateScene(mozart::SceneUpdate* update, + virtual void UpdateScene(SceneUpdateContext& context, mozart::Node* container); #endif @@ -64,6 +58,11 @@ class Layer { 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; + } + // subclasses should assume this will be true by the time Paint() is called bool has_paint_bounds() const { return has_paint_bounds_; } @@ -79,6 +78,7 @@ class Layer { private: ContainerLayer* parent_; + bool needs_system_composite_; bool has_paint_bounds_; // if false, paint_bounds_ is not valid SkRect paint_bounds_; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 1ef68497745..c40090967cf 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -32,14 +32,20 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame, ignore_raster_cache ? nullptr : &frame.context().raster_cache(), frame.gr_context(), SkRect::MakeEmpty(), }; - root_layer_->Preroll(&context, SkMatrix()); + root_layer_->Preroll(&context, SkMatrix::I()); } #if defined(OS_FUCHSIA) -void LayerTree::UpdateScene(mozart::SceneUpdate* update, +void LayerTree::UpdateScene(SceneUpdateContext& context, mozart::Node* container) { TRACE_EVENT0("flutter", "LayerTree::UpdateScene"); - root_layer_->UpdateScene(update, container); + + if (root_layer_->needs_system_composite()) { + root_layer_->UpdateScene(context, container); + } else { + context.AddLayerToCurrentPaintTask(root_layer_.get()); + } + context.FinalizeCurrentPaintTaskIfNeeded(container, SkMatrix::I()); } #endif diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index fcc4d4fb4ba..7421a92dc6e 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -34,7 +34,7 @@ class LayerTree { // TODO(abarth): Integrate scene updates with the rasterization pass so that // we can draw on top of child scenes (and so that we can apply clips and // blending operations to child scene). - void UpdateScene(mozart::SceneUpdate* update, mozart::Node* container); + void UpdateScene(SceneUpdateContext& context, mozart::Node* container); #endif void Paint(CompositorContext::ScopedFrame& frame); diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index 28b3f66fccd..51a070724b7 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -4,14 +4,35 @@ #include "flutter/flow/layers/opacity_layer.h" +#if defined(OS_FUCHSIA) +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/nodes.fidl.h" +#endif // defined(OS_FUCHSIA) + namespace flow { OpacityLayer::OpacityLayer() {} OpacityLayer::~OpacityLayer() {} +#if defined(OS_FUCHSIA) + +void OpacityLayer::UpdateScene(SceneUpdateContext& context, + mozart::Node* container) { + auto node = mozart::Node::New(); + node->op = mozart::NodeOp::New(); + node->op->set_layer(mozart::LayerNodeOp::New()); + node->op->get_layer()->layer_rect = mozart::RectF::From(paint_bounds()); + node->op->get_layer()->blend->alpha = alpha_; + UpdateSceneChildrenInsideNode(context, container, std::move(node)); +} + +#endif // defined(OS_FUCHSIA) + void OpacityLayer::Paint(PaintContext& context) { TRACE_EVENT0("flutter", "OpacityLayer::Paint"); + FTL_DCHECK(!needs_system_composite()); + SkPaint paint; paint.setAlpha(alpha_); diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index f5991b0aab8..1ccea1023a6 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -19,6 +19,11 @@ class OpacityLayer : public ContainerLayer { protected: void Paint(PaintContext& context) override; +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context, + mozart::Node* container) override; +#endif // defined(OS_FUCHSIA) + private: int alpha_; diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 8faaabc9a97..c22a4b54fb0 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -25,8 +25,9 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { matrix, is_complex_, will_change_); } - context->child_paint_bounds = - picture_->cullRect().makeOffset(offset_.x(), offset_.y()); + SkRect bounds = picture_->cullRect().makeOffset(offset_.x(), offset_.y()); + set_paint_bounds(bounds); + context->child_paint_bounds = bounds; } void PictureLayer::Paint(PaintContext& context) { diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 2b7448ad9b2..7817fce8c46 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -4,6 +4,11 @@ #include "flutter/flow/layers/transform_layer.h" +#if defined(OS_FUCHSIA) +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/nodes.fidl.h" +#endif // defined(OS_FUCHSIA) + namespace flow { TransformLayer::TransformLayer() {} @@ -15,10 +20,24 @@ void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { childMatrix.setConcat(matrix, transform_); PrerollChildren(context, childMatrix); transform_.mapRect(&context->child_paint_bounds); + set_paint_bounds(context->child_paint_bounds); } +#if defined(OS_FUCHSIA) + +void TransformLayer::UpdateScene(SceneUpdateContext& context, + mozart::Node* container) { + auto node = mozart::Node::New(); + node->content_transform = mozart::Transform::From(transform_); + UpdateSceneChildrenInsideNode(context, container, std::move(node)); +} + +#endif // defined(OS_FUCHSIA) + void TransformLayer::Paint(PaintContext& context) { TRACE_EVENT0("flutter", "TransformLayer::Paint"); + FTL_DCHECK(!needs_system_composite()); + SkAutoCanvasRestore save(&context.canvas, true); context.canvas.concat(transform_); PaintChildren(context); diff --git a/flow/layers/transform_layer.h b/flow/layers/transform_layer.h index 63439a410f9..dee5fc5796e 100644 --- a/flow/layers/transform_layer.h +++ b/flow/layers/transform_layer.h @@ -16,9 +16,15 @@ class TransformLayer : public ContainerLayer { void set_transform(const SkMatrix& transform) { transform_ = transform; } + protected: void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext& context) override; +#if defined(OS_FUCHSIA) + void UpdateScene(SceneUpdateContext& context, + mozart::Node* container) override; +#endif // defined(OS_FUCHSIA) + private: SkMatrix transform_; diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc new file mode 100644 index 00000000000..06661e072a3 --- /dev/null +++ b/flow/scene_update_context.cc @@ -0,0 +1,127 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/flow/scene_update_context.h" + +#if defined(OS_FUCHSIA) + +#include "apps/mozart/lib/skia/skia_vmo_surface.h" +#include "apps/mozart/lib/skia/type_converters.h" +#include "apps/mozart/services/composition/scenes.fidl.h" +#include "flutter/flow/layers/layer.h" +#include "flutter/glue/trace_event.h" + +namespace flow { + +SceneUpdateContext::CurrentPaintTask::CurrentPaintTask() + : bounds(SkRect::MakeEmpty()) {} + +void SceneUpdateContext::CurrentPaintTask::Clear() { + bounds = SkRect::MakeEmpty(); + layers.clear(); +} + +SceneUpdateContext::SceneUpdateContext(mozart::SceneUpdate* update, + mozart::BufferProducer* buffer_producer) + : update_(update), buffer_producer_(buffer_producer) {} + +SceneUpdateContext::~SceneUpdateContext() = default; + +void SceneUpdateContext::AddLayerToCurrentPaintTask(Layer* layer) { + current_paint_task_.bounds.join(layer->paint_bounds()); + current_paint_task_.layers.push_back(layer); +} + +void SceneUpdateContext::FinalizeCurrentPaintTaskIfNeeded( + mozart::Node* container, + const SkMatrix& ctm) { + if (mozart::NodePtr node = FinalizeCurrentPaintTask(ctm)) + AddChildNode(container, std::move(node)); +} + +mozart::NodePtr SceneUpdateContext::FinalizeCurrentPaintTask( + const SkMatrix& ctm) { + if (current_paint_task_.layers.empty()) + return nullptr; + + const SkRect& bounds = current_paint_task_.bounds; + + SkScalar scaleX = ctm.getScaleX(); + SkScalar scaleY = ctm.getScaleY(); + + SkISize physical_size = + SkISize::Make(bounds.width() * scaleX, bounds.height() * scaleY); + + if (physical_size.isEmpty()) { + current_paint_task_.Clear(); + return nullptr; + } + + mozart::ImagePtr image; + PaintTask task; + task.surface = mozart::MakeSkSurface(physical_size, buffer_producer_, &image); + task.left = bounds.left(); + task.top = bounds.top(); + task.scaleX = scaleX; + task.scaleY = scaleY; + task.layers = std::move(current_paint_task_.layers); + + FTL_DCHECK(task.surface) << "Failed to create surface size=" + << physical_size.width() << "x" + << physical_size.height(); + + paint_tasks_.push_back(task); + + auto resource = mozart::Resource::New(); + resource->set_image(mozart::ImageResource::New()); + resource->get_image()->image = std::move(image); + + auto node = mozart::Node::New(); + node->hit_test_behavior = mozart::HitTestBehavior::New(); + node->op = mozart::NodeOp::New(); + node->op->set_image(mozart::ImageNodeOp::New()); + node->op->get_image()->content_rect = mozart::RectF::From(bounds); + node->op->get_image()->image_resource_id = AddResource(std::move(resource)); + + current_paint_task_.Clear(); + return node; +} + +uint32_t SceneUpdateContext::AddResource(mozart::ResourcePtr resource) { + uint32_t resource_id = next_resource_id_++; + update_->resources.insert(resource_id, std::move(resource)); + return resource_id; +} + +void SceneUpdateContext::AddChildNode(mozart::Node* container, + mozart::NodePtr child) { + uint32_t node_id = next_node_id_++; + update_->nodes.insert(node_id, std::move(child)); + container->child_node_ids.push_back(node_id); +} + +void SceneUpdateContext::ExecutePaintTasks( + CompositorContext::ScopedFrame& frame) { + TRACE_EVENT0("flutter", "SceneUpdateContext::ExecutePaintTasks"); + + for (auto& task : paint_tasks_) { + FTL_DCHECK(task.surface); + SkCanvas* canvas = task.surface->getCanvas(); + Layer::PaintContext context = {*canvas, frame.context().frame_time(), + frame.context().engine_time()}; + + canvas->clear(SK_ColorTRANSPARENT); + canvas->scale(task.scaleX, task.scaleY); + canvas->translate(-task.left, -task.top); + for (Layer* layer : task.layers) + layer->Paint(context); + canvas->flush(); + } + + paint_tasks_.clear(); +} + +} // namespace flow + +#endif // defined(OS_FUCHSIA) diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h new file mode 100644 index 00000000000..4ced4d88b76 --- /dev/null +++ b/flow/scene_update_context.h @@ -0,0 +1,89 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_FLOW_MOZART_SCENE_UPDATE_CONTEXT_H_ +#define FLUTTER_FLOW_MOZART_SCENE_UPDATE_CONTEXT_H_ + +#include +#include + +#include "flutter/flow/compositor_context.h" +#include "lib/ftl/build_config.h" +#include "lib/ftl/logging.h" +#include "lib/ftl/macros.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkSurface.h" + +#if defined(OS_FUCHSIA) +#include "apps/mozart/services/composition/nodes.fidl.h" +#include "apps/mozart/services/composition/resources.fidl.h" +#include "apps/mozart/services/images/image.fidl.h" +#endif // defined(OS_FUCHSIA) + +namespace mozart { +class BufferProducer; +class Node; +class SceneUpdate; +} // namespace mozart + +namespace flow { +class Layer; +class SceneUpdateContext; + +#if defined(OS_FUCHSIA) + +class SceneUpdateContext { + public: + SceneUpdateContext(mozart::SceneUpdate* update, + mozart::BufferProducer* buffer_producer); + ~SceneUpdateContext(); + + mozart::SceneUpdate* update() const { return update_; } + + void AddLayerToCurrentPaintTask(Layer* layer); + void FinalizeCurrentPaintTaskIfNeeded(mozart::Node* container, + const SkMatrix& ctm); + + uint32_t AddResource(mozart::ResourcePtr resource); + void AddChildNode(mozart::Node* container, mozart::NodePtr child); + + void ExecutePaintTasks(CompositorContext::ScopedFrame& frame); + + private: + mozart::NodePtr FinalizeCurrentPaintTask(const SkMatrix& ctm); + + struct CurrentPaintTask { + CurrentPaintTask(); + void Clear(); + + SkRect bounds; + std::vector layers; + }; + + struct PaintTask { + sk_sp surface; + SkScalar left; + SkScalar top; + SkScalar scaleX; + SkScalar scaleY; + std::vector layers; + }; + + mozart::SceneUpdate* update_; + mozart::BufferProducer* buffer_producer_; + + CurrentPaintTask current_paint_task_; + std::vector paint_tasks_; + + uint32_t next_resource_id_ = 1; + uint32_t next_node_id_ = 1; + + FTL_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext); +}; + +#endif // defined(OS_FUCHSIA) + +} // namespace flow + +#endif // FLUTTER_FLOW_MOZART_SCENE_UPDATE_CONTEXT_H_ diff --git a/shell/common/diagnostic/diagnostic_server.cc b/shell/common/diagnostic/diagnostic_server.cc index 73c76fddc6c..8c850b40c9a 100644 --- a/shell/common/diagnostic/diagnostic_server.cc +++ b/shell/common/diagnostic/diagnostic_server.cc @@ -127,7 +127,7 @@ void DiagnosticServer::SkiaPictureTask(Dart_Port port_id) { flow::CompositorContext compositor_context; flow::CompositorContext::ScopedFrame frame = compositor_context.AcquireFrame( - nullptr, *recorder.getRecordingCanvas(), false); + nullptr, recorder.getRecordingCanvas(), false); layer_tree->Raster(frame); sk_sp picture = recorder.finishRecordingAsPicture(); diff --git a/shell/common/platform_view_service_protocol.cc b/shell/common/platform_view_service_protocol.cc index 99f6e05a3f7..8effa833ac0 100644 --- a/shell/common/platform_view_service_protocol.cc +++ b/shell/common/platform_view_service_protocol.cc @@ -253,8 +253,9 @@ bool PlatformViewServiceProtocol::Screenshot(const char* method, if (bitmap.empty()) return ErrorServer(json_object, "no screenshot available"); - sk_sp png(SkImageEncoder::EncodeData( - bitmap, SkImageEncoder::Type::kPNG_Type, SkImageEncoder::kDefaultQuality)); + sk_sp png( + SkImageEncoder::EncodeData(bitmap, SkImageEncoder::Type::kPNG_Type, + SkImageEncoder::kDefaultQuality)); if (!png) return ErrorServer(json_object, "can not encode screenshot"); @@ -295,7 +296,7 @@ void PlatformViewServiceProtocol::ScreenshotGpuTask(SkBitmap* bitmap) { flow::CompositorContext compositor_context; SkCanvas* canvas = surface->getCanvas(); flow::CompositorContext::ScopedFrame frame = - compositor_context.AcquireFrame(nullptr, *canvas, false); + compositor_context.AcquireFrame(nullptr, canvas, false); canvas->clear(SK_ColorBLACK); layer_tree->Raster(frame); diff --git a/shell/gpu/gpu_rasterizer.cc b/shell/gpu/gpu_rasterizer.cc index f21ae29017c..6c683905ec8 100644 --- a/shell/gpu/gpu_rasterizer.cc +++ b/shell/gpu/gpu_rasterizer.cc @@ -130,7 +130,7 @@ void GPURasterizer::DrawToSurface(flow::LayerTree& layer_tree) { } auto compositor_frame = - compositor_context_.AcquireFrame(surface_->GetContext(), *canvas); + compositor_context_.AcquireFrame(surface_->GetContext(), canvas); canvas->clear(SK_ColorBLACK); @@ -173,7 +173,7 @@ void GPURasterizer::DrawToTraceIfNecessary(flow::LayerTree& layer_tree) { layer_tree.frame_size().height()); auto compositor_frame = compositor_context_.AcquireFrame( - nullptr, *recorder.getRecordingCanvas(), false); + nullptr, recorder.getRecordingCanvas(), false); layer_tree.Raster(compositor_frame, true /* ignore raster cache */); sk_sp picture = recorder.finishRecordingAsPicture(); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 56936353e1d..3e5c91c0f69 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -146,8 +146,10 @@ void PlatformViewAndroid::RunBundleAndSnapshot(JNIEnv* env, jstring java_snapshot_override) { std::string bundle_path = base::android::ConvertJavaStringToUTF8(env, java_bundle_path); - std::string snapshot_override = java_snapshot_override ? - base::android::ConvertJavaStringToUTF8(env, java_snapshot_override) : ""; + std::string snapshot_override = + java_snapshot_override + ? base::android::ConvertJavaStringToUTF8(env, java_snapshot_override) + : ""; blink::Threads::UI()->PostTask( [ engine = engine_->GetWeakPtr(), bundle_path, snapshot_override ] { @@ -497,7 +499,7 @@ void PlatformViewAndroid::GetBitmapGpuTask(ftl::AutoResetWaitableEvent* latch, flow::CompositorContext compositor_context; SkCanvas* canvas = surface->getCanvas(); flow::CompositorContext::ScopedFrame frame = - compositor_context.AcquireFrame(nullptr, *canvas, false); + compositor_context.AcquireFrame(nullptr, canvas, false); canvas->clear(SK_ColorBLACK); layer_tree->Raster(frame);