// Copyright 2013 The Flutter 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 "compositor_context.h" #include #include "flutter/flow/layers/layer_tree.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter_runner { class ScopedFrame final : public flutter::CompositorContext::ScopedFrame { public: ScopedFrame(CompositorContext& context, GrDirectContext* gr_context, SkCanvas* canvas, flutter::ExternalViewEmbedder* view_embedder, const SkMatrix& root_surface_transformation, bool instrumentation_enabled, bool surface_supports_readback, fml::RefPtr raster_thread_merger, SessionConnection& session_connection, VulkanSurfaceProducer& surface_producer, std::shared_ptr scene_update_context) : flutter::CompositorContext::ScopedFrame(context, surface_producer.gr_context(), canvas, view_embedder, root_surface_transformation, instrumentation_enabled, surface_supports_readback, raster_thread_merger), session_connection_(session_connection), surface_producer_(surface_producer), scene_update_context_(scene_update_context) {} private: SessionConnection& session_connection_; VulkanSurfaceProducer& surface_producer_; std::shared_ptr scene_update_context_; flutter::RasterStatus Raster(flutter::LayerTree& layer_tree, bool ignore_raster_cache) override { std::vector frame_paint_tasks; std::vector> frame_surfaces; { // Preroll the Flutter layer tree. This allows Flutter to perform // pre-paint optimizations. TRACE_EVENT0("flutter", "Preroll"); layer_tree.Preroll(*this, ignore_raster_cache); } { // Traverse the Flutter layer tree so that the necessary session ops to // represent the frame are enqueued in the underlying session. TRACE_EVENT0("flutter", "UpdateScene"); layer_tree.UpdateScene(scene_update_context_); } { // Flush all pending session ops: create surfaces and enqueue session // Image ops for the frame's paint tasks, then Present. TRACE_EVENT0("flutter", "SessionPresent"); frame_paint_tasks = scene_update_context_->GetPaintTasks(); for (auto& task : frame_paint_tasks) { SkISize physical_size = SkISize::Make(layer_tree.device_pixel_ratio() * task.scale_x * task.paint_bounds.width(), layer_tree.device_pixel_ratio() * task.scale_y * task.paint_bounds.height()); if (physical_size.width() == 0 || physical_size.height() == 0) { frame_surfaces.emplace_back(nullptr); continue; } std::unique_ptr surface = surface_producer_.ProduceSurface(physical_size); if (!surface) { FML_LOG(ERROR) << "Could not acquire a surface from the surface producer " "of size: " << physical_size.width() << "x" << physical_size.height(); } else { task.material.SetTexture(*(surface->GetImage())); } frame_surfaces.emplace_back(std::move(surface)); } session_connection_.Present(); } { // Execute paint tasks in parallel with Scenic's side of the Present, then // signal fences. TRACE_EVENT0("flutter", "ExecutePaintTasks"); size_t surface_index = 0; for (auto& task : frame_paint_tasks) { std::unique_ptr& task_surface = frame_surfaces[surface_index++]; if (!task_surface) { continue; } SkCanvas* canvas = task_surface->GetSkiaSurface()->getCanvas(); flutter::Layer::PaintContext paint_context = { canvas, canvas, gr_context(), nullptr, context().raster_time(), context().ui_time(), context().texture_registry(), &context().raster_cache(), false, layer_tree.device_pixel_ratio()}; canvas->restoreToCount(1); canvas->save(); canvas->clear(task.background_color); canvas->scale(layer_tree.device_pixel_ratio() * task.scale_x, layer_tree.device_pixel_ratio() * task.scale_y); canvas->translate(-task.paint_bounds.left(), -task.paint_bounds.top()); for (flutter::Layer* layer : task.layers) { layer->Paint(paint_context); } } // Tell the surface producer that a present has occurred so it can perform // book-keeping on buffer caches. surface_producer_.OnSurfacesPresented(std::move(frame_surfaces)); } return flutter::RasterStatus::kSuccess; } FML_DISALLOW_COPY_AND_ASSIGN(ScopedFrame); }; CompositorContext::CompositorContext( SessionConnection& session_connection, VulkanSurfaceProducer& surface_producer, std::shared_ptr scene_update_context) : session_connection_(session_connection), surface_producer_(surface_producer), scene_update_context_(scene_update_context) {} CompositorContext::~CompositorContext() = default; std::unique_ptr CompositorContext::AcquireFrame( GrDirectContext* gr_context, SkCanvas* canvas, flutter::ExternalViewEmbedder* view_embedder, const SkMatrix& root_surface_transformation, bool instrumentation_enabled, bool surface_supports_readback, fml::RefPtr raster_thread_merger) { return std::make_unique( *this, gr_context, canvas, view_embedder, root_surface_transformation, instrumentation_enabled, surface_supports_readback, raster_thread_merger, session_connection_, surface_producer_, scene_update_context_); } } // namespace flutter_runner