diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index dd6eac3c39..daa47fd894 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -2114,6 +2114,8 @@ FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan.cc FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan.h FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.cc FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.h +FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_impeller.cc +FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_impeller.h FILE: ../../../flutter/shell/platform/android/AndroidManifest.xml FILE: ../../../flutter/shell/platform/android/android_choreographer.cc FILE: ../../../flutter/shell/platform/android/android_choreographer.h diff --git a/engine/src/flutter/shell/gpu/BUILD.gn b/engine/src/flutter/shell/gpu/BUILD.gn index ef1a6a4687..5e5c1cce53 100644 --- a/engine/src/flutter/shell/gpu/BUILD.gn +++ b/engine/src/flutter/shell/gpu/BUILD.gn @@ -58,6 +58,15 @@ source_set("gpu_surface_vulkan") { "//flutter/vulkan", "//flutter/vulkan/procs", ] + + if (impeller_enable_vulkan) { + sources += [ + "gpu_surface_vulkan_impeller.cc", + "gpu_surface_vulkan_impeller.h", + ] + + public_deps += [ "//flutter/impeller" ] + } } source_set("gpu_surface_metal") { diff --git a/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc b/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc new file mode 100644 index 0000000000..6717c3f8b1 --- /dev/null +++ b/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc @@ -0,0 +1,138 @@ +// 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/shell/gpu/gpu_surface_vulkan_impeller.h" + +#include "flutter/fml/make_copyable.h" +#include "flutter/impeller/display_list/display_list_dispatcher.h" +#include "flutter/impeller/renderer/renderer.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" + +namespace flutter { + +GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller( + std::shared_ptr context) + : weak_factory_(this) { + if (!context || !context->IsValid()) { + return; + } + + auto renderer = std::make_shared(context); + if (!renderer->IsValid()) { + return; + } + + auto aiks_context = std::make_shared(context); + if (!aiks_context->IsValid()) { + return; + } + + impeller_context_ = std::move(context); + impeller_renderer_ = std::move(renderer); + aiks_context_ = std::move(aiks_context); + is_valid_ = true; +} + +// |Surface| +GPUSurfaceVulkanImpeller::~GPUSurfaceVulkanImpeller() = default; + +// |Surface| +bool GPUSurfaceVulkanImpeller::IsValid() { + return is_valid_; +} + +// |Surface| +std::unique_ptr GPUSurfaceVulkanImpeller::AcquireFrame( + const SkISize& size) { + if (!IsValid()) { + FML_LOG(ERROR) << "Vulkan surface was invalid."; + return nullptr; + } + + if (size.isEmpty()) { + FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame."; + return nullptr; + } + + auto& context_vk = impeller::ContextVK::Cast(*impeller_context_); + std::unique_ptr surface = + context_vk.AcquireSurface(frame_num_++); + + auto swap_callback = [weak = weak_factory_.GetWeakPtr()]() -> bool { + if (weak) { + // TODO (kaushikiska@): Invoke the clean-up callback. + // Blocked by - https://github.com/flutter/flutter/issues/112387 + } + return true; + }; + + SurfaceFrame::SubmitCallback submit_callback = + fml::MakeCopyable([renderer = impeller_renderer_, // + aiks_context = aiks_context_, // + surface = std::move(surface) // + ](SurfaceFrame& surface_frame, SkCanvas* canvas) mutable -> bool { + if (!aiks_context) { + return false; + } + + auto display_list = surface_frame.BuildDisplayList(); + if (!display_list) { + FML_LOG(ERROR) << "Could not build display list for surface frame."; + return false; + } + + impeller::DisplayListDispatcher impeller_dispatcher; + display_list->Dispatch(impeller_dispatcher); + auto picture = impeller_dispatcher.EndRecordingAsPicture(); + + return renderer->Render( + std::move(surface), + fml::MakeCopyable( + [aiks_context, picture = std::move(picture)]( + impeller::RenderTarget& render_target) -> bool { + return aiks_context->Render(picture, render_target); + })); + }); + + return std::make_unique( + nullptr, // surface + SurfaceFrame::FramebufferInfo{}, // framebuffer info + submit_callback, // submit callback + size, // frame size + nullptr, // context result + true // display list fallback + ); +} + +// |Surface| +SkMatrix GPUSurfaceVulkanImpeller::GetRootTransformation() const { + // This backend does not currently support root surface transformations. Just + // return identity. + return {}; +} + +// |Surface| +GrDirectContext* GPUSurfaceVulkanImpeller::GetContext() { + // Impeller != Skia. + return nullptr; +} + +// |Surface| +std::unique_ptr +GPUSurfaceVulkanImpeller::MakeRenderContextCurrent() { + // This backend has no such concept. + return std::make_unique(true); +} + +// |Surface| +bool GPUSurfaceVulkanImpeller::EnableRasterCache() const { + return false; +} + +// |Surface| +impeller::AiksContext* GPUSurfaceVulkanImpeller::GetAiksContext() const { + return aiks_context_.get(); +} + +} // namespace flutter diff --git a/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.h b/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.h new file mode 100644 index 0000000000..def6198620 --- /dev/null +++ b/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.h @@ -0,0 +1,56 @@ +// 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. + +#pragma once + +#include "flutter/common/graphics/gl_context_switch.h" +#include "flutter/flow/surface.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/impeller/aiks/aiks_context.h" +#include "flutter/impeller/renderer/context.h" +#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h" + +namespace flutter { + +class GPUSurfaceVulkanImpeller final : public Surface { + public: + explicit GPUSurfaceVulkanImpeller(std::shared_ptr context); + + // |Surface| + ~GPUSurfaceVulkanImpeller() override; + + // |Surface| + bool IsValid() override; + + private: + std::shared_ptr impeller_context_; + std::shared_ptr impeller_renderer_; + std::shared_ptr aiks_context_; + bool is_valid_ = false; + uint64_t frame_num_ = 0; + fml::WeakPtrFactory weak_factory_; + + // |Surface| + std::unique_ptr AcquireFrame(const SkISize& size) override; + + // |Surface| + SkMatrix GetRootTransformation() const override; + + // |Surface| + GrDirectContext* GetContext() override; + + // |Surface| + std::unique_ptr MakeRenderContextCurrent() override; + + // |Surface| + bool EnableRasterCache() const override; + + // |Surface| + impeller::AiksContext* GetAiksContext() const override; + + FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkanImpeller); +}; + +} // namespace flutter diff --git a/engine/src/flutter/vulkan/vulkan_native_surface_android.h b/engine/src/flutter/vulkan/vulkan_native_surface_android.h index 6a7fbec334..2a4eec03f6 100644 --- a/engine/src/flutter/vulkan/vulkan_native_surface_android.h +++ b/engine/src/flutter/vulkan/vulkan_native_surface_android.h @@ -17,7 +17,7 @@ class VulkanNativeSurfaceAndroid : public VulkanNativeSurface { public: /// Create a native surface from the valid ANativeWindow reference. Ownership /// of the ANativeWindow is assumed by this instance. - VulkanNativeSurfaceAndroid(ANativeWindow* native_window); + explicit VulkanNativeSurfaceAndroid(ANativeWindow* native_window); ~VulkanNativeSurfaceAndroid(); diff --git a/engine/src/flutter/vulkan/vulkan_swapchain.cc b/engine/src/flutter/vulkan/vulkan_swapchain.cc index 54dd70d8a6..7e8126e631 100644 --- a/engine/src/flutter/vulkan/vulkan_swapchain.cc +++ b/engine/src/flutter/vulkan/vulkan_swapchain.cc @@ -5,9 +5,12 @@ #include "vulkan_swapchain.h" #include "flutter/vulkan/procs/vulkan_proc_table.h" + +#include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" #include "third_party/skia/include/gpu/vk/GrVkTypes.h" + #include "vulkan_backbuffer.h" #include "vulkan_device.h" #include "vulkan_image.h" @@ -147,11 +150,11 @@ VulkanSwapchain::VulkanSwapchain(const VulkanProcTable& p_vk, return; } - swapchain_ = {swapchain, [this](VkSwapchainKHR swapchain) { - FML_ALLOW_UNUSED_LOCAL(device_.WaitIdle()); - vk.DestroySwapchainKHR(device_.GetHandle(), swapchain, - nullptr); - }}; + swapchain_ = VulkanHandle{ + swapchain, [this](VkSwapchainKHR swapchain) { + FML_ALLOW_UNUSED_LOCAL(device_.WaitIdle()); + vk.DestroySwapchainKHR(device_.GetHandle(), swapchain, nullptr); + }}; if (!CreateSwapchainImages( skia_context, format_infos[format_index].color_type_, @@ -275,7 +278,11 @@ bool VulkanSwapchain::CreateSwapchainImages(GrDirectContext* skia_context, backbuffers_.emplace_back(std::move(backbuffer)); // Populate the image. - auto vulkan_image = std::make_unique(image); + VulkanHandle image_handle = VulkanHandle{ + image, [this](VkImage image) { + vk.DestroyImage(device_.GetHandle(), image, nullptr); + }}; + auto vulkan_image = std::make_unique(std::move(image_handle)); if (!vulkan_image->IsValid()) { return false;