Composite child views in proper paint order (#3243)

We push a bit up the tree during preroll to learn whether there system
composited layers below each layer. During update scene, we squash down
to paint tasks, which we execute after publishing the new scene.
This commit is contained in:
Adam Barth 2016-11-18 12:54:54 -08:00 committed by GitHub
parent e18302e7d1
commit 21f6aa5270
29 changed files with 473 additions and 129 deletions

View File

@ -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<flow::LayerTree> 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<flow::LayerTree> layer_tree,
return;
}
// Get a surface to draw the contents.
mozart::ImagePtr image;
sk_sp<SkSurface> 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<flow::LayerTree> 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();
}

View File

@ -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 {

View File

@ -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_);
}

View File

@ -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();

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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_;

View File

@ -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);

View File

@ -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_;

View File

@ -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);

View File

@ -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_;

View File

@ -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

View File

@ -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<std::unique_ptr<Layer>>& layers() const { return layers_; }
protected:
// Valid only after preroll when needs_system_composite() is true.
const SkMatrix& ctm() const { return ctm_; }
private:
std::vector<std::unique_ptr<Layer>> layers_;
SkMatrix ctm_;
FTL_DISALLOW_COPY_AND_ASSIGN(ContainerLayer);
};

View File

@ -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

View File

@ -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_;

View File

@ -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

View File

@ -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);

View File

@ -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_);

View File

@ -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_;

View File

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

View File

@ -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);

View File

@ -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_;

View File

@ -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)

View File

@ -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 <memory>
#include <vector>
#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<Layer*> layers;
};
struct PaintTask {
sk_sp<SkSurface> surface;
SkScalar left;
SkScalar top;
SkScalar scaleX;
SkScalar scaleY;
std::vector<Layer*> layers;
};
mozart::SceneUpdate* update_;
mozart::BufferProducer* buffer_producer_;
CurrentPaintTask current_paint_task_;
std::vector<PaintTask> 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_

View File

@ -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<SkPicture> picture = recorder.finishRecordingAsPicture();

View File

@ -253,8 +253,9 @@ bool PlatformViewServiceProtocol::Screenshot(const char* method,
if (bitmap.empty())
return ErrorServer(json_object, "no screenshot available");
sk_sp<SkData> png(SkImageEncoder::EncodeData(
bitmap, SkImageEncoder::Type::kPNG_Type, SkImageEncoder::kDefaultQuality));
sk_sp<SkData> 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);

View File

@ -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<SkPicture> picture = recorder.finishRecordingAsPicture();

View File

@ -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);