• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <lib/async/cpp/wait.h>
8 #include <lib/zx/event.h>
9 #include <lib/zx/vmo.h>
10 
11 #include <array>
12 #include <memory>
13 
14 #include "flutter/flow/raster_cache_key.h"
15 #include "flutter/flow/scene_update_context.h"
16 #include "flutter/fml/macros.h"
17 #include "flutter/vulkan/vulkan_command_buffer.h"
18 #include "flutter/vulkan/vulkan_handle.h"
19 #include "flutter/vulkan/vulkan_proc_table.h"
20 #include "flutter/vulkan/vulkan_provider.h"
21 #include "lib/ui/scenic/cpp/resources.h"
22 #include "third_party/skia/include/core/SkSurface.h"
23 
24 namespace flutter_runner {
25 
26 // A |VkImage| and its relevant metadata.
27 struct VulkanImage {
28   VulkanImage() = default;
29   VulkanImage(VulkanImage&&) = default;
30   VulkanImage& operator=(VulkanImage&&) = default;
31 
32   VkExternalMemoryImageCreateInfo vk_external_image_create_info;
33   VkImageCreateInfo vk_image_create_info;
34   VkMemoryRequirements vk_memory_requirements;
35   vulkan::VulkanHandle<VkImage> vk_image;
36 
37   FML_DISALLOW_COPY_AND_ASSIGN(VulkanImage);
38 };
39 
40 // Create a new |VulkanImage| of size |size|, stored in
41 // |out_vulkan_image|.  Returns whether creation of the |VkImage| was
42 // successful.
43 bool CreateVulkanImage(vulkan::VulkanProvider& vulkan_provider,
44                        const SkISize& size,
45                        VulkanImage* out_vulkan_image);
46 
47 class VulkanSurface final
48     : public flutter::SceneUpdateContext::SurfaceProducerSurface {
49  public:
50   VulkanSurface(vulkan::VulkanProvider& vulkan_provider,
51                 sk_sp<GrContext> context,
52                 scenic::Session* session,
53                 const SkISize& size);
54 
55   ~VulkanSurface() override;
56 
57   // |flutter::SceneUpdateContext::SurfaceProducerSurface|
58   size_t AdvanceAndGetAge() override;
59 
60   // |flutter::SceneUpdateContext::SurfaceProducerSurface|
61   bool FlushSessionAcquireAndReleaseEvents() override;
62 
63   // |flutter::SceneUpdateContext::SurfaceProducerSurface|
64   bool IsValid() const override;
65 
66   // |flutter::SceneUpdateContext::SurfaceProducerSurface|
67   SkISize GetSize() const override;
68 
69   // Note: It is safe for the caller to collect the surface in the
70   // |on_writes_committed| callback.
71   void SignalWritesFinished(
72       std::function<void(void)> on_writes_committed) override;
73 
74   // |flutter::SceneUpdateContext::SurfaceProducerSurface|
75   scenic::Image* GetImage() override;
76 
77   // |flutter::SceneUpdateContext::SurfaceProducerSurface|
78   sk_sp<SkSurface> GetSkiaSurface() const override;
79 
GetVkImage()80   const vulkan::VulkanHandle<VkImage>& GetVkImage() {
81     return vulkan_image_.vk_image;
82   }
83 
GetAcquireVkSemaphore()84   const vulkan::VulkanHandle<VkSemaphore>& GetAcquireVkSemaphore() {
85     return acquire_semaphore_;
86   }
87 
GetCommandBuffer(const vulkan::VulkanHandle<VkCommandPool> & pool)88   vulkan::VulkanCommandBuffer* GetCommandBuffer(
89       const vulkan::VulkanHandle<VkCommandPool>& pool) {
90     if (!command_buffer_)
91       command_buffer_ = std::make_unique<vulkan::VulkanCommandBuffer>(
92           vulkan_provider_.vk(), vulkan_provider_.vk_device(), pool);
93     return command_buffer_.get();
94   }
95 
GetCommandBufferFence()96   const vulkan::VulkanHandle<VkFence>& GetCommandBufferFence() {
97     return command_buffer_fence_;
98   }
99 
GetAllocationSize()100   size_t GetAllocationSize() const { return vk_memory_info_.allocationSize; }
101 
GetImageMemoryRequirementsSize()102   size_t GetImageMemoryRequirementsSize() const {
103     return vulkan_image_.vk_memory_requirements.size;
104   }
105 
IsOversized()106   bool IsOversized() const {
107     return GetAllocationSize() > GetImageMemoryRequirementsSize();
108   }
109 
HasStableSizeHistory()110   bool HasStableSizeHistory() const {
111     return std::equal(size_history_.begin() + 1, size_history_.end(),
112                       size_history_.begin());
113   }
114 
115   // Bind |vulkan_image| to |vk_memory_| and create a new skia surface,
116   // replacing the previous |vk_image_|.  |vulkan_image| MUST require less
117   // than or equal the amount of memory contained in |vk_memory_|. Returns
118   // whether the swap was successful.  The |VulkanSurface| will become invalid
119   // if the swap was not successful.
120   bool BindToImage(sk_sp<GrContext> context, VulkanImage vulkan_image);
121 
122   // Flutter may retain a |VulkanSurface| for a |flutter::Layer| subtree to
123   // improve the performance. The |retained_key_| identifies which layer subtree
124   // this |VulkanSurface| is retained for. The key has two parts. One is the
125   // pointer to the root of that layer subtree: |retained_key_.id()|. Another is
126   // the transformation matrix: |retained_key_.matrix()|. We need the matrix
127   // part because a different matrix would invalidate the pixels (raster cache)
128   // in this |VulkanSurface|.
GetRetainedKey()129   const flutter::LayerRasterCacheKey& GetRetainedKey() const {
130     return retained_key_;
131   }
132 
133   // For better safety in retained rendering, Flutter uses a retained
134   // |EntityNode| associated with the retained surface instead of using the
135   // retained surface directly. Hence Flutter can't modify the surface during
136   // retained rendering.
GetRetainedNode()137   const scenic::EntityNode& GetRetainedNode() {
138     used_in_retained_rendering_ = true;
139     return *retained_node_;
140   }
141 
142   // Check whether the retained surface (and its associated |EntityNode|) is
143   // used in the current frame or not. If unused, the |VulkanSurfacePool| will
144   // try to recycle the surface. This flag is reset after each frame.
IsUsedInRetainedRendering()145   bool IsUsedInRetainedRendering() const { return used_in_retained_rendering_; }
ResetIsUsedInRetainedRendering()146   void ResetIsUsedInRetainedRendering() { used_in_retained_rendering_ = false; }
147 
148   // Let this surface own the retained EntityNode associated with it (see
149   // |GetRetainedNode|), and set the retained key (see |GetRetainedKey|).
SetRetainedInfo(const flutter::LayerRasterCacheKey & key,std::unique_ptr<scenic::EntityNode> node)150   void SetRetainedInfo(const flutter::LayerRasterCacheKey& key,
151                        std::unique_ptr<scenic::EntityNode> node) {
152     retained_key_ = key;
153     retained_node_ = std::move(node);
154   }
155 
156  private:
157   static constexpr int kSizeHistorySize = 4;
158 
159   void OnHandleReady(async_dispatcher_t* dispatcher,
160                      async::WaitBase* wait,
161                      zx_status_t status,
162                      const zx_packet_signal_t* signal);
163 
164   bool AllocateDeviceMemory(sk_sp<GrContext> context,
165                             const SkISize& size,
166                             zx::vmo& exported_vmo);
167 
168   bool SetupSkiaSurface(sk_sp<GrContext> context,
169                         const SkISize& size,
170                         SkColorType color_type,
171                         const VkImageCreateInfo& image_create_info,
172                         const VkMemoryRequirements& memory_reqs);
173 
174   bool CreateFences();
175 
176   bool PushSessionImageSetupOps(scenic::Session* session);
177 
178   void Reset();
179 
180   vulkan::VulkanHandle<VkSemaphore> SemaphoreFromEvent(
181       const zx::event& event) const;
182 
183   vulkan::VulkanProvider& vulkan_provider_;
184   scenic::Session* session_;
185   VulkanImage vulkan_image_;
186   vulkan::VulkanHandle<VkDeviceMemory> vk_memory_;
187   VkMemoryAllocateInfo vk_memory_info_;
188   vulkan::VulkanHandle<VkFence> command_buffer_fence_;
189   sk_sp<SkSurface> sk_surface_;
190   // TODO: Don't heap allocate this once SCN-268 is resolved.
191   std::unique_ptr<scenic::Memory> scenic_memory_;
192   std::unique_ptr<scenic::Image> session_image_;
193   zx::event acquire_event_;
194   vulkan::VulkanHandle<VkSemaphore> acquire_semaphore_;
195   std::unique_ptr<vulkan::VulkanCommandBuffer> command_buffer_;
196   zx::event release_event_;
197   async::WaitMethod<VulkanSurface, &VulkanSurface::OnHandleReady> wait_;
198   std::function<void()> pending_on_writes_committed_;
199   std::array<SkISize, kSizeHistorySize> size_history_;
200   int size_history_index_ = 0;
201   size_t age_ = 0;
202   bool valid_ = false;
203 
204   flutter::LayerRasterCacheKey retained_key_ = {0, SkMatrix::MakeScale(1, 1)};
205   std::unique_ptr<scenic::EntityNode> retained_node_ = nullptr;
206 
207   std::atomic<bool> used_in_retained_rendering_ = {false};
208 
209   FML_DISALLOW_COPY_AND_ASSIGN(VulkanSurface);
210 };
211 
212 }  // namespace flutter_runner
213