Skip to content

Commit

Permalink
Composite child views in proper paint order (flutter#3243)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
abarth authored Nov 18, 2016
1 parent e18302e commit 21f6aa5
Show file tree
Hide file tree
Showing 29 changed files with 475 additions and 131 deletions.
48 changes: 10 additions & 38 deletions content_handler/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@

namespace flutter_runner {

namespace {
constexpr uint32_t kContentImageResourceId = 1;
constexpr uint32_t kRootNodeId = mozart::kSceneRootNodeId;
} // namespace

Rasterizer::Rasterizer() {}

Rasterizer::~Rasterizer() {}
Expand All @@ -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));
Expand All @@ -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.
Expand All @@ -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();
}
Expand Down
7 changes: 5 additions & 2 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

source_set("flow") {
sources = [
"bitmap_image.cc",
"bitmap_image.h",
"compositor_context.cc",
"compositor_context.h",
"instrumentation.cc",
Expand Down Expand Up @@ -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",
]

Expand All @@ -57,6 +59,7 @@ source_set("flow") {
"texture_image_none.cc",
]
public_deps = [
"//apps/mozart/lib/skia",
"//apps/mozart/services/composition",
]
} else {
Expand Down
6 changes: 3 additions & 3 deletions flow/compositor_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
}
Expand Down
4 changes: 2 additions & 2 deletions flow/compositor_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class CompositorContext {

ScopedFrame(CompositorContext& context,
GrContext* gr_context,
SkCanvas& canvas,
SkCanvas* canvas,
bool instrumentation_enabled);

friend class CompositorContext;
Expand All @@ -51,7 +51,7 @@ class CompositorContext {
~CompositorContext();

ScopedFrame AcquireFrame(GrContext* gr_context,
SkCanvas& canvas,
SkCanvas* canvas,
bool instrumentation_enabled = true);

void OnGrContextDestroyed();
Expand Down
75 changes: 25 additions & 50 deletions flow/layers/child_scene_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,47 @@

#include "flutter/flow/layers/child_scene_layer.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;
#include "apps/mozart/lib/skia/type_converters.h"
#include "apps/mozart/services/composition/nodes.fidl.h"

} // namespace
namespace flow {

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++;

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 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);
FTL_DCHECK(needs_system_composite());

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 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
2 changes: 1 addition & 1 deletion flow/layers/child_scene_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions flow/layers/clip_path_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions flow/layers/clip_path_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;

Expand Down
18 changes: 18 additions & 0 deletions flow/layers/clip_rect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions flow/layers/clip_rect_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;

Expand Down
18 changes: 18 additions & 0 deletions flow/layers/clip_rrect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions flow/layers/clip_rrect_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;

Expand Down
Loading

0 comments on commit 21f6aa5

Please sign in to comment.