mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
128 lines
4.0 KiB
C++
128 lines
4.0 KiB
C++
// 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->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()};
|
|
|
|
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)
|