|  | // 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 "flutter/lib/ui/compositing/scene.h" | 
|  |  | 
|  | #include "flutter/fml/trace_event.h" | 
|  | #include "flutter/lib/ui/painting/display_list_deferred_image_gpu_skia.h" | 
|  | #include "flutter/lib/ui/painting/image.h" | 
|  | #include "flutter/lib/ui/painting/picture.h" | 
|  | #include "flutter/lib/ui/ui_dart_state.h" | 
|  | #include "flutter/lib/ui/window/platform_configuration.h" | 
|  | #if IMPELLER_SUPPORTS_RENDERING | 
|  | #include "flutter/lib/ui/painting/display_list_deferred_image_gpu_impeller.h" | 
|  | #endif  // IMPELLER_SUPPORTS_RENDERING | 
|  | #include "third_party/skia/include/core/SkImageInfo.h" | 
|  | #include "third_party/skia/include/core/SkSurface.h" | 
|  | #include "third_party/tonic/converter/dart_converter.h" | 
|  | #include "third_party/tonic/dart_args.h" | 
|  | #include "third_party/tonic/dart_binding_macros.h" | 
|  | #include "third_party/tonic/dart_library_natives.h" | 
|  |  | 
|  | namespace flutter { | 
|  |  | 
|  | IMPLEMENT_WRAPPERTYPEINFO(ui, Scene); | 
|  |  | 
|  | void Scene::create(Dart_Handle scene_handle, | 
|  | std::shared_ptr<flutter::Layer> rootLayer, | 
|  | uint32_t rasterizerTracingThreshold, | 
|  | bool checkerboardRasterCacheImages, | 
|  | bool checkerboardOffscreenLayers) { | 
|  | auto scene = fml::MakeRefCounted<Scene>( | 
|  | std::move(rootLayer), rasterizerTracingThreshold, | 
|  | checkerboardRasterCacheImages, checkerboardOffscreenLayers); | 
|  | scene->AssociateWithDartWrapper(scene_handle); | 
|  | } | 
|  |  | 
|  | Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer, | 
|  | uint32_t rasterizerTracingThreshold, | 
|  | bool checkerboardRasterCacheImages, | 
|  | bool checkerboardOffscreenLayers) { | 
|  | layer_tree_config_.root_layer = std::move(rootLayer); | 
|  | layer_tree_config_.rasterizer_tracing_threshold = rasterizerTracingThreshold; | 
|  | layer_tree_config_.checkerboard_raster_cache_images = | 
|  | checkerboardRasterCacheImages; | 
|  | layer_tree_config_.checkerboard_offscreen_layers = | 
|  | checkerboardOffscreenLayers; | 
|  | } | 
|  |  | 
|  | Scene::~Scene() {} | 
|  |  | 
|  | bool Scene::valid() { | 
|  | return layer_tree_config_.root_layer != nullptr; | 
|  | } | 
|  |  | 
|  | void Scene::dispose() { | 
|  | layer_tree_config_.root_layer.reset(); | 
|  | ClearDartWrapper(); | 
|  | } | 
|  |  | 
|  | Dart_Handle Scene::toImageSync(uint32_t width, | 
|  | uint32_t height, | 
|  | Dart_Handle raw_image_handle) { | 
|  | TRACE_EVENT0("flutter", "Scene::toImageSync"); | 
|  |  | 
|  | if (!valid()) { | 
|  | return tonic::ToDart("Scene has been disposed."); | 
|  | } | 
|  |  | 
|  | Scene::RasterizeToImage(width, height, raw_image_handle); | 
|  | return Dart_Null(); | 
|  | } | 
|  |  | 
|  | Dart_Handle Scene::toImage(uint32_t width, | 
|  | uint32_t height, | 
|  | Dart_Handle raw_image_callback) { | 
|  | TRACE_EVENT0("flutter", "Scene::toImage"); | 
|  |  | 
|  | if (!valid()) { | 
|  | return tonic::ToDart("Scene has been disposed."); | 
|  | } | 
|  |  | 
|  | return Picture::RasterizeLayerTreeToImage(BuildLayerTree(width, height), | 
|  | raw_image_callback); | 
|  | } | 
|  |  | 
|  | static sk_sp<DlImage> CreateDeferredImage( | 
|  | bool impeller, | 
|  | std::unique_ptr<LayerTree> layer_tree, | 
|  | fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate, | 
|  | fml::RefPtr<fml::TaskRunner> raster_task_runner, | 
|  | fml::RefPtr<SkiaUnrefQueue> unref_queue) { | 
|  | #if IMPELLER_SUPPORTS_RENDERING | 
|  | if (impeller) { | 
|  | return DlDeferredImageGPUImpeller::Make(std::move(layer_tree), | 
|  | std::move(snapshot_delegate), | 
|  | std::move(raster_task_runner)); | 
|  | } | 
|  | #endif  // IMPELLER_SUPPORTS_RENDERING | 
|  |  | 
|  | const auto& frame_size = layer_tree->frame_size(); | 
|  | const SkImageInfo image_info = | 
|  | SkImageInfo::Make(frame_size.width(), frame_size.height(), | 
|  | kRGBA_8888_SkColorType, kPremul_SkAlphaType); | 
|  | return DlDeferredImageGPUSkia::MakeFromLayerTree( | 
|  | image_info, std::move(layer_tree), std::move(snapshot_delegate), | 
|  | raster_task_runner, std::move(unref_queue)); | 
|  | } | 
|  |  | 
|  | void Scene::RasterizeToImage(uint32_t width, | 
|  | uint32_t height, | 
|  | Dart_Handle raw_image_handle) { | 
|  | auto* dart_state = UIDartState::Current(); | 
|  | if (!dart_state) { | 
|  | return; | 
|  | } | 
|  | auto unref_queue = dart_state->GetSkiaUnrefQueue(); | 
|  | auto snapshot_delegate = dart_state->GetSnapshotDelegate(); | 
|  | auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner(); | 
|  |  | 
|  | auto image = CanvasImage::Create(); | 
|  | auto dl_image = CreateDeferredImage( | 
|  | dart_state->IsImpellerEnabled(), BuildLayerTree(width, height), | 
|  | std::move(snapshot_delegate), std::move(raster_task_runner), | 
|  | std::move(unref_queue)); | 
|  | image->set_image(dl_image); | 
|  | image->AssociateWithDartWrapper(raw_image_handle); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree(uint64_t width, | 
|  | uint64_t height) { | 
|  | return BuildLayerTree(width, height); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<LayerTree> Scene::BuildLayerTree(uint32_t width, | 
|  | uint32_t height) { | 
|  | if (!valid()) { | 
|  | return nullptr; | 
|  | } | 
|  | return std::make_unique<LayerTree>(layer_tree_config_, | 
|  | SkISize::Make(width, height)); | 
|  | } | 
|  |  | 
|  | }  // namespace flutter |