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