blob: e0f5ebd1e247d37e29189846d4dbbdc1cab40fa1 [file] [log] [blame]
// 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,
SurfaceProducer* surface_producer)
: update_(update), surface_producer_(surface_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 = surface_producer_->ProduceSurface(physical_size, &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->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(),
frame.context().memory_usage(),
false};
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)