| // 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. |
| |
| #ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FUCHSIA_EXTERNAL_VIEW_EMBEDDER_H_ |
| #define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FUCHSIA_EXTERNAL_VIEW_EMBEDDER_H_ |
| |
| #include <fuchsia/ui/views/cpp/fidl.h> |
| #include <lib/ui/scenic/cpp/resources.h> |
| #include <lib/ui/scenic/cpp/view_ref_pair.h> |
| |
| #include <cstdint> // For uint32_t & uint64_t |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "flutter/flow/embedded_views.h" |
| #include "flutter/fml/logging.h" |
| #include "flutter/fml/macros.h" |
| #include "flutter/shell/common/canvas_spy.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkPictureRecorder.h" |
| #include "third_party/skia/include/core/SkPoint.h" |
| #include "third_party/skia/include/core/SkSize.h" |
| #include "third_party/skia/include/gpu/GrDirectContext.h" |
| |
| #include "session_connection.h" |
| #include "vulkan_surface_producer.h" |
| |
| namespace flutter_runner { |
| |
| // This class orchestrates interaction with the Scenic compositor on Fuchsia. It |
| // ensures that flutter content and platform view content are both rendered |
| // correctly in a unified scene. |
| class FuchsiaExternalViewEmbedder final : public flutter::ExternalViewEmbedder { |
| public: |
| FuchsiaExternalViewEmbedder(std::string debug_label, |
| fuchsia::ui::views::ViewToken view_token, |
| scenic::ViewRefPair view_ref_pair, |
| SessionConnection& session, |
| VulkanSurfaceProducer& surface_producer); |
| ~FuchsiaExternalViewEmbedder(); |
| |
| // |ExternalViewEmbedder| |
| SkCanvas* GetRootCanvas() override; |
| |
| // |ExternalViewEmbedder| |
| std::vector<SkCanvas*> GetCurrentCanvases() override; |
| |
| // |ExternalViewEmbedder| |
| void PrerollCompositeEmbeddedView( |
| int view_id, |
| std::unique_ptr<flutter::EmbeddedViewParams> params) override; |
| |
| // |ExternalViewEmbedder| |
| SkCanvas* CompositeEmbeddedView(int view_id) override; |
| |
| // |ExternalViewEmbedder| |
| flutter::PostPrerollResult PostPrerollAction( |
| fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override; |
| |
| // |ExternalViewEmbedder| |
| void BeginFrame( |
| SkISize frame_size, |
| GrDirectContext* context, |
| double device_pixel_ratio, |
| fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override; |
| |
| // |ExternalViewEmbedder| |
| void EndFrame( |
| bool should_resubmit_frame, |
| fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override; |
| |
| // |ExternalViewEmbedder| |
| void SubmitFrame(GrDirectContext* context, |
| std::unique_ptr<flutter::SurfaceFrame> frame) override; |
| |
| // |ExternalViewEmbedder| |
| void CancelFrame() override { Reset(); } |
| |
| // |ExternalViewEmbedder| |
| bool SupportsDynamicThreadMerging() override { return false; } |
| |
| // View manipulation. |
| // |SetViewProperties| doesn't manipulate the view directly -- it sets |
| // prending properties for the next |UpdateView| call. |
| void EnableWireframe(bool enable); |
| void CreateView(int64_t view_id); |
| void DestroyView(int64_t view_id); |
| void SetViewProperties(int64_t view_id, bool hit_testable, bool focusable); |
| |
| private: |
| // Reset state for a new frame. |
| void Reset(); |
| |
| struct EmbedderLayer { |
| EmbedderLayer(const SkISize& frame_size, |
| std::optional<flutter::EmbeddedViewParams> view_params) |
| : embedded_view_params(std::move(view_params)), |
| recorder(std::make_unique<SkPictureRecorder>()), |
| canvas_spy(std::make_unique<flutter::CanvasSpy>( |
| recorder->beginRecording(frame_size.width(), |
| frame_size.height()))), |
| surface_size(frame_size) {} |
| |
| std::optional<flutter::EmbeddedViewParams> embedded_view_params; |
| std::unique_ptr<SkPictureRecorder> recorder; |
| std::unique_ptr<flutter::CanvasSpy> canvas_spy; |
| SkISize surface_size; |
| }; |
| |
| struct ScenicView { |
| scenic::OpacityNodeHACK opacity_node; |
| scenic::EntityNode entity_node; |
| scenic::ViewHolder view_holder; |
| |
| SkPoint offset = SkPoint::Make(0.f, 0.f); |
| SkSize size = SkSize::MakeEmpty(); |
| float elevation = 0.f; |
| float opacity = 1.f; |
| bool hit_testable = false; |
| bool focusable = false; |
| |
| bool pending_hit_testable = false; |
| bool pending_focusable = false; |
| }; |
| |
| struct ScenicLayer { |
| scenic::ShapeNode shape_node; |
| scenic::Material material; |
| }; |
| |
| using EmbedderLayerId = std::optional<uint32_t>; |
| constexpr static EmbedderLayerId kRootLayerId = EmbedderLayerId{}; |
| |
| SessionConnection& session_; |
| VulkanSurfaceProducer& surface_producer_; |
| |
| scenic::View root_view_; |
| scenic::EntityNode metrics_node_; |
| scenic::EntityNode root_node_; |
| |
| std::unordered_map<uint64_t, std::vector<scenic::Rectangle>> scenic_rects_; |
| std::unordered_map<int64_t, ScenicView> scenic_views_; |
| std::vector<ScenicLayer> scenic_layers_; |
| |
| std::unordered_map<EmbedderLayerId, EmbedderLayer> frame_layers_; |
| std::vector<EmbedderLayerId> frame_composition_order_; |
| SkISize frame_size_ = SkISize::Make(0, 0); |
| float frame_dpr_ = 1.f; |
| |
| FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaExternalViewEmbedder); |
| }; |
| |
| } // namespace flutter_runner |
| |
| #endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FUCHSIA_EXTERNAL_VIEW_EMBEDDER_H_ |