| // 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_FLOW_SCENE_UPDATE_CONTEXT_H_ |
| #define FLUTTER_FLOW_SCENE_UPDATE_CONTEXT_H_ |
| |
| #include <fuchsia/ui/views/cpp/fidl.h> |
| #include <lib/ui/scenic/cpp/resources.h> |
| #include <lib/ui/scenic/cpp/session.h> |
| #include <lib/ui/scenic/cpp/view_ref_pair.h> |
| |
| #include <cfloat> |
| #include <memory> |
| #include <set> |
| #include <vector> |
| |
| #include "flutter/flow/embedded_views.h" |
| #include "flutter/fml/logging.h" |
| #include "flutter/fml/macros.h" |
| #include "third_party/skia/include/core/SkRect.h" |
| #include "third_party/skia/include/core/SkSurface.h" |
| |
| namespace flutter { |
| |
| class Layer; |
| |
| // Scenic currently lacks an API to enable rendering of alpha channel; this only |
| // happens if there is a OpacityNode higher in the tree with opacity != 1. For |
| // now, clamp to a infinitesimally smaller value than 1, which does not cause |
| // visual problems in practice. |
| constexpr float kOneMinusEpsilon = 1 - FLT_EPSILON; |
| |
| // How much layers are separated in Scenic z elevation. |
| constexpr float kScenicZElevationBetweenLayers = 10.f; |
| |
| class SessionWrapper { |
| public: |
| virtual ~SessionWrapper() {} |
| |
| virtual scenic::Session* get() = 0; |
| virtual void Present() = 0; |
| }; |
| |
| class SceneUpdateContext : public flutter::ExternalViewEmbedder { |
| public: |
| class Entity { |
| public: |
| Entity(SceneUpdateContext& context); |
| virtual ~Entity(); |
| |
| SceneUpdateContext& context() { return context_; } |
| scenic::EntityNode& entity_node() { return entity_node_; } |
| virtual scenic::ContainerNode& embedder_node() { return entity_node_; } |
| |
| private: |
| SceneUpdateContext& context_; |
| Entity* const previous_entity_; |
| |
| scenic::EntityNode entity_node_; |
| }; |
| |
| class Transform : public Entity { |
| public: |
| Transform(SceneUpdateContext& context, const SkMatrix& transform); |
| Transform(SceneUpdateContext& context, |
| float scale_x, |
| float scale_y, |
| float scale_z); |
| virtual ~Transform(); |
| |
| private: |
| float const previous_scale_x_; |
| float const previous_scale_y_; |
| }; |
| |
| class Frame : public Entity { |
| public: |
| // When layer is not nullptr, the frame is associated with a layer subtree |
| // rooted with that layer. The frame may then create a surface that will be |
| // retained for that layer. |
| Frame(SceneUpdateContext& context, |
| const SkRRect& rrect, |
| SkColor color, |
| SkAlpha opacity, |
| std::string label); |
| virtual ~Frame(); |
| |
| scenic::ContainerNode& embedder_node() override { return opacity_node_; } |
| |
| void AddPaintLayer(Layer* layer); |
| |
| private: |
| const float previous_elevation_; |
| |
| const SkRRect rrect_; |
| SkColor const color_; |
| SkAlpha const opacity_; |
| |
| scenic::OpacityNodeHACK opacity_node_; |
| std::vector<Layer*> paint_layers_; |
| SkRect paint_bounds_; |
| }; |
| |
| class Clip : public Entity { |
| public: |
| Clip(SceneUpdateContext& context, const SkRect& shape_bounds); |
| ~Clip() = default; |
| }; |
| |
| struct PaintTask { |
| SkRect paint_bounds; |
| SkScalar scale_x; |
| SkScalar scale_y; |
| SkColor background_color; |
| scenic::Material material; |
| std::vector<Layer*> layers; |
| }; |
| |
| SceneUpdateContext(std::string debug_label, |
| fuchsia::ui::views::ViewToken view_token, |
| scenic::ViewRefPair view_ref_pair, |
| SessionWrapper& session); |
| ~SceneUpdateContext() = default; |
| |
| scenic::ContainerNode& root_node() { return root_node_; } |
| |
| // The cumulative alpha value based on all the parent OpacityLayers. |
| void set_alphaf(float alpha) { alpha_ = alpha; } |
| float alphaf() { return alpha_; } |
| |
| // Returns all `PaintTask`s generated for the current frame. |
| std::vector<PaintTask> GetPaintTasks(); |
| |
| // Enable/disable wireframe rendering around the root view bounds. |
| void EnableWireframe(bool enable); |
| |
| // Reset state for a new frame. |
| void Reset(); |
| |
| // |ExternalViewEmbedder| |
| SkCanvas* GetRootCanvas() override { return nullptr; } |
| |
| // |ExternalViewEmbedder| |
| void CancelFrame() override {} |
| |
| // |ExternalViewEmbedder| |
| void BeginFrame( |
| SkISize frame_size, |
| GrDirectContext* context, |
| double device_pixel_ratio, |
| fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {} |
| |
| // |ExternalViewEmbedder| |
| void PrerollCompositeEmbeddedView( |
| int view_id, |
| std::unique_ptr<EmbeddedViewParams> params) override {} |
| |
| // |ExternalViewEmbedder| |
| std::vector<SkCanvas*> GetCurrentCanvases() override { |
| return std::vector<SkCanvas*>(); |
| } |
| |
| // |ExternalViewEmbedder| |
| virtual SkCanvas* CompositeEmbeddedView(int view_id) override { |
| return nullptr; |
| } |
| |
| void CreateView(int64_t view_id, bool hit_testable, bool focusable); |
| void UpdateView(int64_t view_id, bool hit_testable, bool focusable); |
| void DestroyView(int64_t view_id); |
| void UpdateView(int64_t view_id, |
| const SkPoint& offset, |
| const SkSize& size, |
| std::optional<bool> override_hit_testable = std::nullopt); |
| |
| private: |
| void CreateFrame(scenic::EntityNode& entity_node, |
| const SkRRect& rrect, |
| SkColor color, |
| SkAlpha opacity, |
| const SkRect& paint_bounds, |
| std::vector<Layer*> paint_layers); |
| |
| SessionWrapper& session_; |
| |
| scenic::View root_view_; |
| scenic::EntityNode root_node_; |
| |
| std::vector<PaintTask> paint_tasks_; |
| |
| Entity* top_entity_ = nullptr; |
| float top_scale_x_ = 1.f; |
| float top_scale_y_ = 1.f; |
| float top_elevation_ = 0.f; |
| |
| float next_elevation_ = 0.f; |
| float alpha_ = 1.f; |
| |
| FML_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext); |
| }; |
| |
| } // namespace flutter |
| |
| #endif // FLUTTER_FLOW_SCENE_UPDATE_CONTEXT_H_ |