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