diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 9f3dafd9aca8c..5311da160f013 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -177,6 +177,8 @@ ../../../flutter/impeller/renderer/backend/vulkan/fence_waiter_vk_unittests.cc ../../../flutter/impeller/renderer/backend/vulkan/render_pass_cache_unittests.cc ../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk_unittests.cc +../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/README.md +../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/README.md ../../../flutter/impeller/renderer/backend/vulkan/test ../../../flutter/impeller/renderer/blit_pass_unittests.cc ../../../flutter/impeller/renderer/capabilities_unittests.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 3d33f51e5d590..46c438f18bdcc 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -35234,8 +35234,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc + ../../../flutter/LICENSE @@ -35297,12 +35297,18 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/shared_object_vk.cc + ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/shared_object_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/surface_context_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/surface_context_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/surface_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/surface_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_image_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_image_vk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/texture_source_vk.cc + ../../../flutter/LICENSE @@ -35445,6 +35451,16 @@ ORIGIN: ../../../flutter/impeller/tessellator/c/tessellator.h + ../../../flutter ORIGIN: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/tessellator/tessellator.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/tessellator/tessellator.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/hardware_buffer.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/hardware_buffer.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/native_window.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/native_window.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/proc_table.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/proc_table.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/surface_control.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/surface_control.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/surface_transaction.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/android/surface_transaction.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/egl/config.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/egl/config.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/egl/context.cc + ../../../flutter/LICENSE @@ -38084,8 +38100,8 @@ FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc @@ -38148,12 +38164,18 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/shared_object_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/shared_object_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/surface_context_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/surface_context_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/surface_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/surface_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_image_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_image_vk.h -FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc -FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_impl_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/swapchain_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/texture_source_vk.cc @@ -38296,6 +38318,16 @@ FILE: ../../../flutter/impeller/tessellator/c/tessellator.h FILE: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart FILE: ../../../flutter/impeller/tessellator/tessellator.cc FILE: ../../../flutter/impeller/tessellator/tessellator.h +FILE: ../../../flutter/impeller/toolkit/android/hardware_buffer.cc +FILE: ../../../flutter/impeller/toolkit/android/hardware_buffer.h +FILE: ../../../flutter/impeller/toolkit/android/native_window.cc +FILE: ../../../flutter/impeller/toolkit/android/native_window.h +FILE: ../../../flutter/impeller/toolkit/android/proc_table.cc +FILE: ../../../flutter/impeller/toolkit/android/proc_table.h +FILE: ../../../flutter/impeller/toolkit/android/surface_control.cc +FILE: ../../../flutter/impeller/toolkit/android/surface_control.h +FILE: ../../../flutter/impeller/toolkit/android/surface_transaction.cc +FILE: ../../../flutter/impeller/toolkit/android/surface_transaction.h FILE: ../../../flutter/impeller/toolkit/egl/config.cc FILE: ../../../flutter/impeller/toolkit/egl/config.h FILE: ../../../flutter/impeller/toolkit/egl/context.cc diff --git a/impeller/BUILD.gn b/impeller/BUILD.gn index 79dbd862f1fa3..bd3277cb5ec95 100644 --- a/impeller/BUILD.gn +++ b/impeller/BUILD.gn @@ -42,6 +42,10 @@ config("impeller_public_config") { defines += [ "IMPELLER_TRACE_ALL_GL_CALLS" ] } + if (is_android) { + defines += [ "__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__" ] + } + if (is_win) { defines += [ # TODO(dnfield): https://github.com/flutter/flutter/issues/50053 diff --git a/impeller/playground/backend/gles/playground_impl_gles.cc b/impeller/playground/backend/gles/playground_impl_gles.cc index 4eb970a55a756..82945835a76b0 100644 --- a/impeller/playground/backend/gles/playground_impl_gles.cc +++ b/impeller/playground/backend/gles/playground_impl_gles.cc @@ -165,7 +165,7 @@ PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() const { } // |PlaygroundImpl| -std::unique_ptr PlaygroundImplGLES::AcquireSurfaceFrame( +std::shared_ptr PlaygroundImplGLES::AcquireSurfaceFrame( std::shared_ptr context) { auto window = reinterpret_cast(GetWindowHandle()); int width = 0; diff --git a/impeller/playground/backend/gles/playground_impl_gles.h b/impeller/playground/backend/gles/playground_impl_gles.h index 21a51fd9ab807..85b99e1a13cb5 100644 --- a/impeller/playground/backend/gles/playground_impl_gles.h +++ b/impeller/playground/backend/gles/playground_impl_gles.h @@ -36,7 +36,7 @@ class PlaygroundImplGLES final : public PlaygroundImpl { WindowHandle GetWindowHandle() const override; // |PlaygroundImpl| - std::unique_ptr AcquireSurfaceFrame( + std::shared_ptr AcquireSurfaceFrame( std::shared_ptr context) override; PlaygroundImplGLES(const PlaygroundImplGLES&) = delete; diff --git a/impeller/playground/backend/metal/playground_impl_mtl.h b/impeller/playground/backend/metal/playground_impl_mtl.h index 9d8698d2857d7..b018852b925c3 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.h +++ b/impeller/playground/backend/metal/playground_impl_mtl.h @@ -46,7 +46,7 @@ class PlaygroundImplMTL final : public PlaygroundImpl { WindowHandle GetWindowHandle() const override; // |PlaygroundImpl| - std::unique_ptr AcquireSurfaceFrame( + std::shared_ptr AcquireSurfaceFrame( std::shared_ptr context) override; PlaygroundImplMTL(const PlaygroundImplMTL&) = delete; diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 421d6eba3c46b..f13b0f45f03e0 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -107,7 +107,7 @@ } // |PlaygroundImpl| -std::unique_ptr PlaygroundImplMTL::AcquireSurfaceFrame( +std::shared_ptr PlaygroundImplMTL::AcquireSurfaceFrame( std::shared_ptr context) { if (!data_->metal_layer) { return nullptr; diff --git a/impeller/playground/backend/vulkan/playground_impl_vk.cc b/impeller/playground/backend/vulkan/playground_impl_vk.cc index f980674e2410b..9d3b4b89a7cb2 100644 --- a/impeller/playground/backend/vulkan/playground_impl_vk.cc +++ b/impeller/playground/backend/vulkan/playground_impl_vk.cc @@ -20,7 +20,7 @@ #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/surface_context_vk.h" -#include "impeller/renderer/backend/vulkan/surface_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h" #include "impeller/renderer/backend/vulkan/texture_vk.h" #include "impeller/renderer/vk/compute_shaders_vk.h" #include "impeller/scene/shaders/vk/scene_shaders_vk.h" @@ -142,7 +142,7 @@ PlaygroundImpl::WindowHandle PlaygroundImplVK::GetWindowHandle() const { } // |PlaygroundImpl| -std::unique_ptr PlaygroundImplVK::AcquireSurfaceFrame( +std::shared_ptr PlaygroundImplVK::AcquireSurfaceFrame( std::shared_ptr context) { SurfaceContextVK* surface_context_vk = reinterpret_cast(context_.get()); diff --git a/impeller/playground/backend/vulkan/playground_impl_vk.h b/impeller/playground/backend/vulkan/playground_impl_vk.h index 83237b34da64a..e9de32d13d25b 100644 --- a/impeller/playground/backend/vulkan/playground_impl_vk.h +++ b/impeller/playground/backend/vulkan/playground_impl_vk.h @@ -40,7 +40,7 @@ class PlaygroundImplVK final : public PlaygroundImpl { WindowHandle GetWindowHandle() const override; // |PlaygroundImpl| - std::unique_ptr AcquireSurfaceFrame( + std::shared_ptr AcquireSurfaceFrame( std::shared_ptr context) override; PlaygroundImplVK(const PlaygroundImplVK&) = delete; diff --git a/impeller/playground/playground_impl.h b/impeller/playground/playground_impl.h index 68598d398553d..4ff65751321ff 100644 --- a/impeller/playground/playground_impl.h +++ b/impeller/playground/playground_impl.h @@ -28,7 +28,7 @@ class PlaygroundImpl { virtual std::shared_ptr GetContext() const = 0; - virtual std::unique_ptr AcquireSurfaceFrame( + virtual std::shared_ptr AcquireSurfaceFrame( std::shared_ptr context) = 0; Vector2 GetContentScale() const; diff --git a/impeller/renderer/backend/gles/surface_gles.cc b/impeller/renderer/backend/gles/surface_gles.cc index f32c5131d1fa7..d5eb1e9ef6292 100644 --- a/impeller/renderer/backend/gles/surface_gles.cc +++ b/impeller/renderer/backend/gles/surface_gles.cc @@ -86,7 +86,7 @@ SurfaceGLES::SurfaceGLES(SwapCallback swap_callback, SurfaceGLES::~SurfaceGLES() = default; // |Surface| -bool SurfaceGLES::Present() const { +bool SurfaceGLES::Present() { return swap_callback_ ? swap_callback_() : false; } diff --git a/impeller/renderer/backend/gles/surface_gles.h b/impeller/renderer/backend/gles/surface_gles.h index 1b040598d3994..4af803db7de23 100644 --- a/impeller/renderer/backend/gles/surface_gles.h +++ b/impeller/renderer/backend/gles/surface_gles.h @@ -35,7 +35,7 @@ class SurfaceGLES final : public Surface { SurfaceGLES(SwapCallback swap_callback, const RenderTarget& target_desc); // |Surface| - bool Present() const override; + bool Present() override; SurfaceGLES(const SurfaceGLES&) = delete; diff --git a/impeller/renderer/backend/metal/surface_mtl.h b/impeller/renderer/backend/metal/surface_mtl.h index a933ecff87a36..f328e78db8f0e 100644 --- a/impeller/renderer/backend/metal/surface_mtl.h +++ b/impeller/renderer/backend/metal/surface_mtl.h @@ -60,7 +60,7 @@ class SurfaceMTL final : public Surface { IRect coverage() const; // |Surface| - bool Present() const override; + bool Present() override; private: std::weak_ptr context_; diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index f23cbfbe13895..0ea52aa1b30a2 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -223,7 +223,7 @@ - (void)flutterPrepareForPresent:(nonnull id)commandBuffer; } // |Surface| -bool SurfaceMTL::Present() const { +bool SurfaceMTL::Present() { auto context = context_.lock(); if (!context) { return false; diff --git a/impeller/renderer/backend/vulkan/BUILD.gn b/impeller/renderer/backend/vulkan/BUILD.gn index 20ee2f02dad44..447a533cf6a63 100644 --- a/impeller/renderer/backend/vulkan/BUILD.gn +++ b/impeller/renderer/backend/vulkan/BUILD.gn @@ -34,8 +34,6 @@ impeller_component("vulkan") { sources = [ "allocator_vk.cc", "allocator_vk.h", - "android_hardware_buffer_texture_source_vk.cc", - "android_hardware_buffer_texture_source_vk.h", "barrier_vk.cc", "barrier_vk.h", "blit_command_vk.cc", @@ -97,12 +95,14 @@ impeller_component("vulkan") { "shared_object_vk.h", "surface_context_vk.cc", "surface_context_vk.h", - "surface_vk.cc", - "surface_vk.h", - "swapchain_image_vk.cc", - "swapchain_image_vk.h", - "swapchain_impl_vk.cc", - "swapchain_impl_vk.h", + "swapchain/khr/khr_surface_vk.cc", + "swapchain/khr/khr_surface_vk.h", + "swapchain/khr/khr_swapchain_image_vk.cc", + "swapchain/khr/khr_swapchain_image_vk.h", + "swapchain/khr/khr_swapchain_impl_vk.cc", + "swapchain/khr/khr_swapchain_impl_vk.h", + "swapchain/khr/khr_swapchain_vk.cc", + "swapchain/khr/khr_swapchain_vk.h", "swapchain_vk.cc", "swapchain_vk.h", "texture_source_vk.cc", @@ -130,4 +130,16 @@ impeller_component("vulkan") { "//flutter/third_party/vulkan-deps/vulkan-headers/src:vulkan_headers", "//third_party/vulkan_memory_allocator", ] + + if (is_android) { + sources += [ + "android/ahb_texture_source_vk.cc", + "android/ahb_texture_source_vk.h", + "swapchain/ahb/ahb_surface_vk.cc", + "swapchain/ahb/ahb_surface_vk.h", + "swapchain/ahb/ahb_swapchain_vk.cc", + "swapchain/ahb/ahb_swapchain_vk.h", + ] + public_deps += [ "../../../toolkit/android" ] + } } diff --git a/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc similarity index 88% rename from impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc rename to impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc index 0ec9e2725ff02..152db1583abc6 100644 --- a/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc +++ b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h" +#include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" #include @@ -10,8 +10,6 @@ #include "impeller/renderer/backend/vulkan/texture_source_vk.h" #include "impeller/renderer/backend/vulkan/yuv_conversion_library_vk.h" -#ifdef FML_OS_ANDROID - namespace impeller { using AHBProperties = vk::StructureChain< @@ -293,17 +291,18 @@ static TextureDescriptor ToTextureDescriptor( return desc; } -AndroidHardwareBufferTextureSourceVK::AndroidHardwareBufferTextureSourceVK( - const std::shared_ptr& context, - struct AHardwareBuffer* ahb, - const AHardwareBuffer_Desc& ahb_desc) +AHBTextureSourceVK::AHBTextureSourceVK(const std::shared_ptr& context, + struct AHardwareBuffer* ahb, + const AHardwareBuffer_Desc& ahb_desc) : TextureSourceVK(ToTextureDescriptor(ahb_desc)) { if (!context) { VALIDATION_LOG << "Invalid context."; return; } - const auto& device = context->GetDevice(); + const auto& context_vk = ContextVK::Cast(*context); + + const auto& device = context_vk.GetDevice(); AHBProperties ahb_props; @@ -340,7 +339,7 @@ AndroidHardwareBufferTextureSourceVK::AndroidHardwareBufferTextureSourceVK( } // Figure out how to perform YUV conversions. - auto yuv_conversion = CreateYUVConversion(*context, ahb_props); + auto yuv_conversion = CreateYUVConversion(context_vk, ahb_props); if (!yuv_conversion || !yuv_conversion->IsValid()) { return; } @@ -363,50 +362,61 @@ AndroidHardwareBufferTextureSourceVK::AndroidHardwareBufferTextureSourceVK( image_view_ = std::move(image_view); #ifdef IMPELLER_DEBUG - context->SetDebugName(device_memory_.get(), "AHB Device Memory"); - context->SetDebugName(image_.get(), "AHB Image"); - context->SetDebugName(yuv_conversion_->GetConversion(), "AHB YUV Conversion"); - context->SetDebugName(image_view_.get(), "AHB ImageView"); + context_vk.SetDebugName(device_memory_.get(), "AHB Device Memory"); + context_vk.SetDebugName(image_.get(), "AHB Image"); + context_vk.SetDebugName(yuv_conversion_->GetConversion(), + "AHB YUV Conversion"); + context_vk.SetDebugName(image_view_.get(), "AHB ImageView"); #endif // IMPELLER_DEBUG is_valid_ = true; } +AHBTextureSourceVK::AHBTextureSourceVK( + const std::shared_ptr& context, + std::shared_ptr hardware_buffer) + : AHBTextureSourceVK(context, + hardware_buffer->GetHandle(), + hardware_buffer->GetAndroidDescriptor()) { + hardware_buffer_ = std::move(hardware_buffer); + is_valid_ = is_valid_ && hardware_buffer_ && hardware_buffer_->IsValid(); +} + // |TextureSourceVK| -AndroidHardwareBufferTextureSourceVK::~AndroidHardwareBufferTextureSourceVK() = - default; +AHBTextureSourceVK::~AHBTextureSourceVK() = default; -bool AndroidHardwareBufferTextureSourceVK::IsValid() const { +const std::shared_ptr& +AHBTextureSourceVK::GetHardwareBuffer() const { + return hardware_buffer_; +} + +bool AHBTextureSourceVK::IsValid() const { return is_valid_; } // |TextureSourceVK| -vk::Image AndroidHardwareBufferTextureSourceVK::GetImage() const { +vk::Image AHBTextureSourceVK::GetImage() const { return image_.get(); } // |TextureSourceVK| -vk::ImageView AndroidHardwareBufferTextureSourceVK::GetImageView() const { +vk::ImageView AHBTextureSourceVK::GetImageView() const { return image_view_.get(); } // |TextureSourceVK| -vk::ImageView AndroidHardwareBufferTextureSourceVK::GetRenderTargetView() - const { +vk::ImageView AHBTextureSourceVK::GetRenderTargetView() const { return image_view_.get(); } // |TextureSourceVK| -bool AndroidHardwareBufferTextureSourceVK::IsSwapchainImage() const { +bool AHBTextureSourceVK::IsSwapchainImage() const { return false; } // |TextureSourceVK| -std::shared_ptr -AndroidHardwareBufferTextureSourceVK::GetYUVConversion() const { +std::shared_ptr AHBTextureSourceVK::GetYUVConversion() const { return needs_yuv_conversion_ ? yuv_conversion_ : nullptr; } } // namespace impeller - -#endif diff --git a/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h similarity index 67% rename from impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h rename to impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h index 724308cb2b6fb..ef6176595faa0 100644 --- a/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h +++ b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h @@ -2,23 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ANDROID_HARDWARE_BUFFER_TEXTURE_SOURCE_VK_H_ -#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ANDROID_HARDWARE_BUFFER_TEXTURE_SOURCE_VK_H_ +#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ANDROID_AHB_TEXTURE_SOURCE_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ANDROID_AHB_TEXTURE_SOURCE_VK_H_ -#include "flutter/fml/build_config.h" -#include "vulkan/vulkan_core.h" - -#ifdef FML_OS_ANDROID +#include +#include +#include "flutter/fml/build_config.h" #include "flutter/fml/macros.h" #include "impeller/geometry/size.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/texture_source_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/backend/vulkan/yuv_conversion_vk.h" - -#include -#include +#include "impeller/toolkit/android/hardware_buffer.h" namespace impeller { @@ -36,15 +33,19 @@ class ContextVK; /// descriptors. The objects are meant to be used directly (either /// as render targets or sources for sampling), not copied. /// -class AndroidHardwareBufferTextureSourceVK final : public TextureSourceVK { +class AHBTextureSourceVK final : public TextureSourceVK { public: - AndroidHardwareBufferTextureSourceVK( - const std::shared_ptr& context, - struct AHardwareBuffer* hardware_buffer, - const AHardwareBuffer_Desc& hardware_buffer_desc); + AHBTextureSourceVK(const std::shared_ptr& context, + struct AHardwareBuffer* hardware_buffer, + const AHardwareBuffer_Desc& hardware_buffer_desc); + + AHBTextureSourceVK(const std::shared_ptr& context, + std::shared_ptr buffer); // |TextureSourceVK| - ~AndroidHardwareBufferTextureSourceVK() override; + ~AHBTextureSourceVK() override; + + const std::shared_ptr& GetHardwareBuffer() const; // |TextureSourceVK| vk::Image GetImage() const override; @@ -64,6 +65,7 @@ class AndroidHardwareBufferTextureSourceVK final : public TextureSourceVK { std::shared_ptr GetYUVConversion() const override; private: + std::shared_ptr hardware_buffer_; vk::UniqueDeviceMemory device_memory_; vk::UniqueImage image_; vk::UniqueImageView image_view_; @@ -71,15 +73,11 @@ class AndroidHardwareBufferTextureSourceVK final : public TextureSourceVK { bool needs_yuv_conversion_ = false; bool is_valid_ = false; - AndroidHardwareBufferTextureSourceVK( - const AndroidHardwareBufferTextureSourceVK&) = delete; + AHBTextureSourceVK(const AHBTextureSourceVK&) = delete; - AndroidHardwareBufferTextureSourceVK& operator=( - const AndroidHardwareBufferTextureSourceVK&) = delete; + AHBTextureSourceVK& operator=(const AHBTextureSourceVK&) = delete; }; } // namespace impeller -#endif - -#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ANDROID_HARDWARE_BUFFER_TEXTURE_SOURCE_VK_H_ +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ANDROID_AHB_TEXTURE_SOURCE_VK_H_ diff --git a/impeller/renderer/backend/vulkan/surface_context_vk.cc b/impeller/renderer/backend/vulkan/surface_context_vk.cc index f0a7912433d4b..44fc9d52d05f5 100644 --- a/impeller/renderer/backend/vulkan/surface_context_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_context_vk.cc @@ -4,12 +4,17 @@ #include "impeller/renderer/backend/vulkan/surface_context_vk.h" +#include "flutter/fml/build_config.h" #include "flutter/fml/trace_event.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" -#include "impeller/renderer/backend/vulkan/swapchain_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h" #include "impeller/renderer/surface.h" +#if FML_OS_ANDROID +#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h" +#endif // #FML_OS_ANDROID + namespace impeller { SurfaceContextVK::SurfaceContextVK(const std::shared_ptr& parent) @@ -64,7 +69,7 @@ void SurfaceContextVK::Shutdown() { bool SurfaceContextVK::SetWindowSurface(vk::UniqueSurfaceKHR surface, const ISize& size) { - auto swapchain = SwapchainVK::Create(parent_, std::move(surface), size); + auto swapchain = KHRSwapchainVK::Create(parent_, std::move(surface), size); if (!swapchain) { VALIDATION_LOG << "Could not create swapchain."; return false; @@ -77,7 +82,23 @@ bool SurfaceContextVK::SetWindowSurface(vk::UniqueSurfaceKHR surface, return true; } -std::unique_ptr SurfaceContextVK::AcquireNextSurface() { +#ifdef FML_OS_ANDROID + +bool SurfaceContextVK::SetWindowSurface(ANativeWindow* window) { + if (!parent_->GetInstance()) { + return false; + } + auto swapchain = AHBSwapchainVK::Create(parent_, window); + if (!swapchain) { + return false; + } + swapchain_ = std::move(swapchain); + return true; +} + +#endif // FML_OS_ANDROID + +std::shared_ptr SurfaceContextVK::AcquireNextSurface() { TRACE_EVENT0("impeller", __FUNCTION__); auto surface = swapchain_ ? swapchain_->AcquireNextDrawable() : nullptr; if (!surface) { @@ -93,32 +114,12 @@ std::unique_ptr SurfaceContextVK::AcquireNextSurface() { } void SurfaceContextVK::UpdateSurfaceSize(const ISize& size) const { - swapchain_->UpdateSurfaceSize(size); -} - -#ifdef FML_OS_ANDROID - -vk::UniqueSurfaceKHR SurfaceContextVK::CreateAndroidSurface( - ANativeWindow* window) const { - if (!parent_->GetInstance()) { - return vk::UniqueSurfaceKHR{VK_NULL_HANDLE}; + if (!swapchain_) { + return; } - - auto create_info = vk::AndroidSurfaceCreateInfoKHR().setWindow(window); - auto surface_res = - parent_->GetInstance().createAndroidSurfaceKHRUnique(create_info); - - if (surface_res.result != vk::Result::eSuccess) { - VALIDATION_LOG << "Could not create Android surface, error: " - << vk::to_string(surface_res.result); - return vk::UniqueSurfaceKHR{VK_NULL_HANDLE}; - } - - return std::move(surface_res.value); + swapchain_->UpdateSurfaceSize(size); } -#endif // FML_OS_ANDROID - const vk::Device& SurfaceContextVK::GetDevice() const { return parent_->GetDevice(); } diff --git a/impeller/renderer/backend/vulkan/surface_context_vk.h b/impeller/renderer/backend/vulkan/surface_context_vk.h index 76f691411c7e8..c47bc37e33ca7 100644 --- a/impeller/renderer/backend/vulkan/surface_context_vk.h +++ b/impeller/renderer/backend/vulkan/surface_context_vk.h @@ -72,7 +72,11 @@ class SurfaceContextVK : public Context, [[nodiscard]] bool SetWindowSurface(vk::UniqueSurfaceKHR surface, const ISize& size); - std::unique_ptr AcquireNextSurface(); +#ifdef FML_OS_ANDROID + [[nodiscard]] bool SetWindowSurface(ANativeWindow* window); +#endif // FML_OS_ANDROID + + std::shared_ptr AcquireNextSurface(); /// @brief Mark the current swapchain configuration as dirty, forcing it to be /// recreated on the next frame. @@ -80,10 +84,6 @@ class SurfaceContextVK : public Context, void InitializeCommonlyUsedShadersIfNeeded() const override; -#ifdef FML_OS_ANDROID - vk::UniqueSurfaceKHR CreateAndroidSurface(ANativeWindow* window) const; -#endif // FML_OS_ANDROID - const vk::Device& GetDevice() const; private: diff --git a/impeller/renderer/backend/vulkan/surface_vk.h b/impeller/renderer/backend/vulkan/surface_vk.h deleted file mode 100644 index ea4203135324c..0000000000000 --- a/impeller/renderer/backend/vulkan/surface_vk.h +++ /dev/null @@ -1,45 +0,0 @@ -// 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_IMPELLER_RENDERER_BACKEND_VULKAN_SURFACE_VK_H_ -#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SURFACE_VK_H_ - -#include - -#include "flutter/fml/macros.h" -#include "impeller/renderer/backend/vulkan/context_vk.h" -#include "impeller/renderer/backend/vulkan/swapchain_image_vk.h" -#include "impeller/renderer/surface.h" - -namespace impeller { - -class SurfaceVK final : public Surface { - public: - using SwapCallback = std::function; - - static std::unique_ptr WrapSwapchainImage( - const std::shared_ptr& context, - std::shared_ptr& swapchain_image, - SwapCallback swap_callback, - bool enable_msaa = true); - - // |Surface| - ~SurfaceVK() override; - - private: - SwapCallback swap_callback_; - - SurfaceVK(const RenderTarget& target, SwapCallback swap_callback); - - // |Surface| - bool Present() const override; - - SurfaceVK(const SurfaceVK&) = delete; - - SurfaceVK& operator=(const SurfaceVK&) = delete; -}; - -} // namespace impeller - -#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SURFACE_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain/ahb/README.md b/impeller/renderer/backend/vulkan/swapchain/ahb/README.md new file mode 100644 index 0000000000000..de922c292765c --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/ahb/README.md @@ -0,0 +1,4 @@ +Android Hardware Buffer Backed Swapchain +======================================== + +Swapchain implementation used on Android API versions above 29. diff --git a/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.cc b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.cc new file mode 100644 index 0000000000000..6f311d8b6d973 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.cc @@ -0,0 +1,87 @@ +// 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 "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h" + +#include "impeller/core/texture.h" +#include "impeller/renderer/backend/vulkan/texture_vk.h" + +namespace impeller { + +std::shared_ptr AHBSurfaceVK::WrapSwapchainImage( + const std::shared_ptr& context, + std::weak_ptr weak_swapchain, + std::shared_ptr swapchain_image) { + if (!swapchain_image || !swapchain_image->IsValid() || !context) { + VALIDATION_LOG << "Invalid swapchain image to wrap."; + return nullptr; + } + + TextureDescriptor msaa_tex_desc; + msaa_tex_desc.storage_mode = StorageMode::kDeviceTransient; + msaa_tex_desc.type = TextureType::kTexture2DMultisample; + msaa_tex_desc.sample_count = SampleCount::kCount4; + msaa_tex_desc.format = swapchain_image->GetTextureDescriptor().format; + msaa_tex_desc.size = swapchain_image->GetTextureDescriptor().size; + msaa_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); + msaa_tex_desc.compression_type = CompressionType::kLossy; + + auto msaa_tex = context->GetResourceAllocator()->CreateTexture(msaa_tex_desc); + auto resolve_tex = std::make_shared(context, swapchain_image); + + if (!msaa_tex || !resolve_tex) { + return nullptr; + } + + ColorAttachment color0; + color0.clear_color = Color::DarkSlateGray(); + color0.load_action = LoadAction::kClear; + color0.texture = msaa_tex; + color0.resolve_texture = resolve_tex; + color0.store_action = StoreAction::kMultisampleResolve; + + RenderTarget render_target; + render_target.SetColorAttachment(color0, 0u); + + auto surface = std::shared_ptr(new AHBSurfaceVK( + render_target, // + std::move(weak_swapchain), // + std::move(swapchain_image) // + )); + if (!surface->IsValid()) { + VALIDATION_LOG << "Surface for wrapped swapchain image was invalid."; + return nullptr; + } + return surface; +} + +AHBSurfaceVK::AHBSurfaceVK(const RenderTarget& render_target, + std::weak_ptr weak_swapchain, + std::shared_ptr swapchain_image) + : Surface(render_target), + weak_swapchain_(std::move(weak_swapchain)), + swapchain_image_(std::move(swapchain_image)) {} + +AHBSurfaceVK::~AHBSurfaceVK() = default; + +// |Surface| +bool AHBSurfaceVK::Present() { + if (!swapchain_image_) { + VALIDATION_LOG << "Invalid swapchain image."; + return false; + } + auto swapchain = weak_swapchain_.lock(); + if (!swapchain) { + VALIDATION_LOG << "Swapchain died before presentation."; + return false; + } + return swapchain->PresentSurface(shared_from_this()); +} + +const std::shared_ptr& AHBSurfaceVK::GetTextureSource() + const { + return swapchain_image_; +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h new file mode 100644 index 0000000000000..96e9e94c5bc80 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h @@ -0,0 +1,46 @@ +// 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_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_AHB_SURFACE_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_AHB_SURFACE_VK_H_ + +#include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h" +#include "impeller/renderer/render_target.h" +#include "impeller/renderer/surface.h" + +namespace impeller { + +class AHBSurfaceVK final : public Surface, + public std::enable_shared_from_this { + public: + static std::shared_ptr WrapSwapchainImage( + const std::shared_ptr& context, + std::weak_ptr weak_swapchain, + std::shared_ptr swapchain_image); + + // |Surface| + ~AHBSurfaceVK() override; + + AHBSurfaceVK(const AHBSurfaceVK&) = delete; + + AHBSurfaceVK& operator=(const AHBSurfaceVK&) = delete; + + // |Surface| + bool Present() override; + + const std::shared_ptr& GetTextureSource() const; + + private: + std::weak_ptr weak_swapchain_; + std::shared_ptr swapchain_image_; + + AHBSurfaceVK(const RenderTarget& render_target, + std::weak_ptr weak_swapchain, + std::shared_ptr texture); +}; + +} // namespace impeller + +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_AHB_SURFACE_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc new file mode 100644 index 0000000000000..63d0a21f3d786 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc @@ -0,0 +1,231 @@ +// 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 "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h" + +#include "flutter/fml/closure.h" +#include "flutter/fml/trace_event.h" +#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_surface_vk.h" +#include "impeller/toolkit/android/surface_transaction.h" + +namespace impeller { + +static constexpr vk::Format ToVKFormat(android::HardwareBufferFormat format) { + switch (format) { + case android::HardwareBufferFormat::kR8G8B8A8UNormInt: + return vk::Format::eR8G8B8A8Unorm; + } + FML_UNREACHABLE(); +} + +std::shared_ptr AHBSwapchainVK::Create( + const std::shared_ptr& context, + ANativeWindow* window, + size_t max_drawable_count) { + auto swapchain = std::shared_ptr( + new AHBSwapchainVK(context, window, max_drawable_count)); + if (!swapchain->IsValid()) { + VALIDATION_LOG << "Could not create valid AHB swapchain."; + return nullptr; + } + return swapchain; +} + +AHBSwapchainVK::AHBSwapchainVK(const std::shared_ptr& context, + ANativeWindow* window, + size_t max_drawable_count) + : context_(context), + native_window_(std::make_shared(window)), + drawable_count_sema_(max_drawable_count) { + if (!context || !drawable_count_sema_.IsValid()) { + return; + } + + if (!native_window_->IsValid()) { + VALIDATION_LOG << "Invalid window when creating a swapchain."; + return; + } + + auto surface_control = std::make_shared( + native_window_->GetHandle(), "FlutterImpellerVulkan"); + + if (!surface_control->IsValid()) { + VALIDATION_LOG << "Could not create surface control from window."; + return; + } + + desc_ = android::HardwareBufferDescriptor::MakeForSwapchainImage( + native_window_->GetSize()); + + if (!desc_.IsAllocatable()) { + VALIDATION_LOG << "Hardware buffer is not allocatable."; + return; + } + + ContextVK::Cast(*context).SetOffscreenFormat( + ToPixelFormat(ToVKFormat(desc_.format))); + + surface_control_ = std::move(surface_control); + is_valid_ = true; +} + +AHBSwapchainVK::~AHBSwapchainVK() = default; + +// |SwapchainVK| +bool AHBSwapchainVK::IsValid() const { + return is_valid_; +} + +// |SwapchainVK| +vk::Format AHBSwapchainVK::GetSurfaceFormat() const { + Lock lock(mutex_); + return ToVKFormat(desc_.format); +} + +// |SwapchainVK| +void AHBSwapchainVK::UpdateSurfaceSize(const ISize& size) { + TRACE_EVENT0("impeller", __FUNCTION__); + + Lock lock(mutex_); + + if (desc_.size == size) { + return; + } + + auto new_desc = desc_; + new_desc.size = size; + if (!new_desc.IsAllocatable()) { + VALIDATION_LOG << "New surface size is not allocatable."; + return; + } + + desc_ = new_desc; +} + +std::shared_ptr AHBSwapchainVK::CreateNewSurface() { + TRACE_EVENT0("impeller", __FUNCTION__); + + auto ahb = std::make_unique(desc_); + if (!ahb || !ahb->IsValid()) { + VALIDATION_LOG << "Could not create hardware buffer."; + return nullptr; + } + auto context = context_.lock(); + if (!context) { + VALIDATION_LOG << "Context died during image acquisition."; + return nullptr; + } + auto texture = std::make_shared(context, std::move(ahb)); + if (!texture->IsValid()) { + VALIDATION_LOG << "Could not wrap hardware buffer into a texture."; + return nullptr; + } + auto surface = AHBSurfaceVK::WrapSwapchainImage(context, weak_from_this(), + std::move(texture)); + if (!surface->IsValid()) { + VALIDATION_LOG << "Could not create surface with wrapped texture."; + return nullptr; + } + return surface; +} + +// |SwapchainVK| +std::shared_ptr AHBSwapchainVK::AcquireNextDrawable() { + TRACE_EVENT0("impeller", __FUNCTION__); + + { + TRACE_EVENT0("impeller", "CompositorBackpressure"); + // Accompanying signal is in the call to recycle the surface after the + // compositor is done using it. + if (!drawable_count_sema_.Wait()) { + VALIDATION_LOG << "Failed waiting for drawable acquisition."; + return nullptr; + } + } + + Lock lock(mutex_); + + if (auto surface = PopRecyclable()) { + FML_LOG(IMPORTANT) << "Recycled surface."; + return surface; + } + + if (auto surface = CreateNewSurface()) { + FML_LOG(IMPORTANT) << "Created surface."; + return surface; + } + + return nullptr; +} + +bool AHBSwapchainVK::PresentSurface( + const std::shared_ptr& surface) { + // We must signal the drawables semaphore in all cases. Otherwise, new + // drawable acquisitions may wait forever. In case we fail before the + // compositor even attempts to use the surface, recycle it. + fml::ScopedCleanupClosure recycle_on_fail( + [&]() { OnSurfaceDidCompleteBeingUsedByCompositor(surface); }); + + if (!surface) { + return false; + } + + auto texture = surface->GetTextureSource(); + + if (!texture || !IsValid()) { + VALIDATION_LOG << "Invalid texture to present."; + return false; + } + + android::SurfaceTransaction transaction; + if (!transaction.SetContents(surface_control_.get(), + texture->GetHardwareBuffer().get())) { + VALIDATION_LOG << "Could not set surface contents."; + return false; + } + + if (!transaction.Apply([surface, weak = weak_from_this()]() { + auto thiz = weak.lock(); + if (!thiz) { + return; + } + thiz->OnSurfaceDidCompleteBeingUsedByCompositor(surface); + })) { + VALIDATION_LOG << "Could not apply surface transaction."; + return false; + } + + // The compositor owns our surface now and will recycle the texture in the + // completion callback. + recycle_on_fail.Release(); + return true; +} + +void AHBSwapchainVK::OnSurfaceDidCompleteBeingUsedByCompositor( + const std::shared_ptr& surface) { + { + Lock lock(mutex_); + PushRecyclable(surface); + } + drawable_count_sema_.Signal(); +} + +void AHBSwapchainVK::PushRecyclable( + const std::shared_ptr& surface) { + // recyclable_.push_back(Recyclable{std::move(surface)}); + // FML_LOG(IMPORTANT) << "There are " << recyclable_.size() << " + // recyclables."; +} + +std::shared_ptr AHBSwapchainVK::PopRecyclable() { + return nullptr; + // if (recyclable_.empty()) { + // return nullptr; + // } + // auto surface = recyclable_.back().surface; + // recyclable_.pop_back(); + // return surface; +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h new file mode 100644 index 0000000000000..e4e40f913a080 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h @@ -0,0 +1,91 @@ +// 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_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_AHB_SWAPCHAIN_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_AHB_SWAPCHAIN_VK_H_ + +#include +#include + +#include "flutter/fml/synchronization/semaphore.h" +#include "impeller/base/thread.h" +#include "impeller/base/timing.h" +#include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain_vk.h" +#include "impeller/renderer/backend/vulkan/texture_vk.h" +#include "impeller/toolkit/android/hardware_buffer.h" +#include "impeller/toolkit/android/native_window.h" +#include "impeller/toolkit/android/surface_control.h" + +namespace impeller { + +class AHBSurfaceVK; + +class AHBSwapchainVK final + : public SwapchainVK, + public std::enable_shared_from_this { + public: + static std::shared_ptr Create( + const std::shared_ptr& context, + ANativeWindow* window, + size_t max_drawable_count = 3u); + + // |SwapchainVK| + ~AHBSwapchainVK() override; + + AHBSwapchainVK(const AHBSwapchainVK&) = delete; + + AHBSwapchainVK& operator=(const AHBSwapchainVK&) = delete; + + // |SwapchainVK| + bool IsValid() const override; + + // |SwapchainVK| + vk::Format GetSurfaceFormat() const override; + + // |SwapchainVK| + std::shared_ptr AcquireNextDrawable() override; + + // |SwapchainVK| + void UpdateSurfaceSize(const ISize& size) override; + + bool PresentSurface(const std::shared_ptr& surface); + + private: + struct Recyclable { + TimePoint last_use; + std::shared_ptr surface; + + explicit Recyclable(std::shared_ptr p_surface) + : last_use(Clock::now()), surface(std::move(p_surface)) {} + }; + + std::weak_ptr context_; + std::shared_ptr native_window_; + std::shared_ptr surface_control_; + fml::Semaphore drawable_count_sema_; + mutable Mutex mutex_; + android::HardwareBufferDescriptor desc_ IPLR_GUARDED_BY(mutex_); + std::deque recyclable_ IPLR_GUARDED_BY(mutex_); + bool is_valid_ = false; + + AHBSwapchainVK(const std::shared_ptr& context, + ANativeWindow* window, + size_t max_drawable_count); + + void OnSurfaceDidCompleteBeingUsedByCompositor( + const std::shared_ptr& surface); + + std::shared_ptr CreateNewSurface() IPLR_REQUIRES(mutex_); + + void PushRecyclable(const std::shared_ptr& surface) + IPLR_REQUIRES(mutex_); + + std::shared_ptr PopRecyclable() IPLR_REQUIRES(mutex_); +}; + +} // namespace impeller + +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_AHB_AHB_SWAPCHAIN_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain/khr/README.md b/impeller/renderer/backend/vulkan/swapchain/khr/README.md new file mode 100644 index 0000000000000..d9fa22bf7cd93 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/khr/README.md @@ -0,0 +1,4 @@ +VK_KHR_surface based Swapchain +============================== + +Used on all platforms [except Android](../ahb/README.md). diff --git a/impeller/renderer/backend/vulkan/surface_vk.cc b/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.cc similarity index 83% rename from impeller/renderer/backend/vulkan/surface_vk.cc rename to impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.cc index c5700a7783949..0dc8ce841d2e5 100644 --- a/impeller/renderer/backend/vulkan/surface_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.cc @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "impeller/renderer/backend/vulkan/surface_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h" #include "impeller/core/formats.h" -#include "impeller/renderer/backend/vulkan/swapchain_image_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h" #include "impeller/renderer/backend/vulkan/texture_vk.h" #include "impeller/renderer/surface.h" namespace impeller { -std::unique_ptr SurfaceVK::WrapSwapchainImage( +std::unique_ptr KHRSurfaceVK::WrapSwapchainImage( const std::shared_ptr& context, - std::shared_ptr& swapchain_image, + std::shared_ptr& swapchain_image, SwapCallback swap_callback, bool enable_msaa) { if (!context || !swapchain_image || !swap_callback) { @@ -79,16 +79,17 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( render_target_desc.SetColorAttachment(color0, 0u); // The constructor is private. So make_unique may not be used. - return std::unique_ptr( - new SurfaceVK(render_target_desc, std::move(swap_callback))); + return std::unique_ptr( + new KHRSurfaceVK(render_target_desc, std::move(swap_callback))); } -SurfaceVK::SurfaceVK(const RenderTarget& target, SwapCallback swap_callback) +KHRSurfaceVK::KHRSurfaceVK(const RenderTarget& target, + SwapCallback swap_callback) : Surface(target), swap_callback_(std::move(swap_callback)) {} -SurfaceVK::~SurfaceVK() = default; +KHRSurfaceVK::~KHRSurfaceVK() = default; -bool SurfaceVK::Present() const { +bool KHRSurfaceVK::Present() { return swap_callback_ ? swap_callback_() : false; } diff --git a/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h b/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h new file mode 100644 index 0000000000000..3b9398458ef05 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h @@ -0,0 +1,45 @@ +// 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_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SURFACE_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SURFACE_VK_H_ + +#include + +#include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h" +#include "impeller/renderer/surface.h" + +namespace impeller { + +class KHRSurfaceVK final : public Surface { + public: + using SwapCallback = std::function; + + static std::unique_ptr WrapSwapchainImage( + const std::shared_ptr& context, + std::shared_ptr& swapchain_image, + SwapCallback swap_callback, + bool enable_msaa = true); + + // |Surface| + ~KHRSurfaceVK() override; + + private: + SwapCallback swap_callback_; + + KHRSurfaceVK(const RenderTarget& target, SwapCallback swap_callback); + + // |Surface| + bool Present() override; + + KHRSurfaceVK(const KHRSurfaceVK&) = delete; + + KHRSurfaceVK& operator=(const KHRSurfaceVK&) = delete; +}; + +} // namespace impeller + +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SURFACE_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain_image_vk.cc b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc similarity index 59% rename from impeller/renderer/backend/vulkan/swapchain_image_vk.cc rename to impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc index c6fc383a4c2e9..a537138a359bd 100644 --- a/impeller/renderer/backend/vulkan/swapchain_image_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "impeller/renderer/backend/vulkan/swapchain_image_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h" namespace impeller { -SwapchainImageVK::SwapchainImageVK(TextureDescriptor desc, - const vk::Device& device, - vk::Image image) +KHRSwapchainImageVK::KHRSwapchainImageVK(TextureDescriptor desc, + const vk::Device& device, + vk::Image image) : TextureSourceVK(desc), image_(image) { vk::ImageViewCreateInfo view_info; view_info.image = image_; @@ -29,44 +29,44 @@ SwapchainImageVK::SwapchainImageVK(TextureDescriptor desc, is_valid_ = true; } -SwapchainImageVK::~SwapchainImageVK() = default; +KHRSwapchainImageVK::~KHRSwapchainImageVK() = default; -bool SwapchainImageVK::IsValid() const { +bool KHRSwapchainImageVK::IsValid() const { return is_valid_; } -std::shared_ptr SwapchainImageVK::GetMSAATexture() const { +std::shared_ptr KHRSwapchainImageVK::GetMSAATexture() const { return msaa_tex_; } -bool SwapchainImageVK::HasMSAATexture() const { +bool KHRSwapchainImageVK::HasMSAATexture() const { return msaa_tex_ != nullptr; } -void SwapchainImageVK::SetMSAATexture(std::shared_ptr msaa_tex) { +void KHRSwapchainImageVK::SetMSAATexture(std::shared_ptr msaa_tex) { msaa_tex_ = std::move(msaa_tex); } -PixelFormat SwapchainImageVK::GetPixelFormat() const { +PixelFormat KHRSwapchainImageVK::GetPixelFormat() const { return desc_.format; } -ISize SwapchainImageVK::GetSize() const { +ISize KHRSwapchainImageVK::GetSize() const { return desc_.size; } // |TextureSourceVK| -vk::Image SwapchainImageVK::GetImage() const { +vk::Image KHRSwapchainImageVK::GetImage() const { return image_; } // |TextureSourceVK| -vk::ImageView SwapchainImageVK::GetImageView() const { +vk::ImageView KHRSwapchainImageVK::GetImageView() const { return image_view_.get(); } // |TextureSourceVK| -vk::ImageView SwapchainImageVK::GetRenderTargetView() const { +vk::ImageView KHRSwapchainImageVK::GetRenderTargetView() const { return image_view_.get(); } diff --git a/impeller/renderer/backend/vulkan/swapchain_image_vk.h b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h similarity index 64% rename from impeller/renderer/backend/vulkan/swapchain_image_vk.h rename to impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h index 48673ebe4845d..f0db0bf352a3c 100644 --- a/impeller/renderer/backend/vulkan/swapchain_image_vk.h +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_IMAGE_VK_H_ -#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_IMAGE_VK_H_ +#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_IMAGE_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_IMAGE_VK_H_ #include "impeller/geometry/size.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" @@ -13,14 +13,14 @@ namespace impeller { -class SwapchainImageVK final : public TextureSourceVK { +class KHRSwapchainImageVK final : public TextureSourceVK { public: - SwapchainImageVK(TextureDescriptor desc, - const vk::Device& device, - vk::Image image); + KHRSwapchainImageVK(TextureDescriptor desc, + const vk::Device& device, + vk::Image image); // |TextureSourceVK| - ~SwapchainImageVK() override; + ~KHRSwapchainImageVK() override; bool IsValid() const; @@ -50,11 +50,11 @@ class SwapchainImageVK final : public TextureSourceVK { std::shared_ptr msaa_tex_; bool is_valid_ = false; - SwapchainImageVK(const SwapchainImageVK&) = delete; + KHRSwapchainImageVK(const KHRSwapchainImageVK&) = delete; - SwapchainImageVK& operator=(const SwapchainImageVK&) = delete; + KHRSwapchainImageVK& operator=(const KHRSwapchainImageVK&) = delete; }; } // namespace impeller -#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_IMAGE_VK_H_ +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_IMAGE_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc similarity index 89% rename from impeller/renderer/backend/vulkan/swapchain_impl_vk.cc rename to impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc index 76411732c004a..fa45c44212f41 100644 --- a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "impeller/renderer/backend/vulkan/swapchain_impl_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h" #include "fml/synchronization/semaphore.h" #include "impeller/base/validation.h" @@ -11,8 +11,8 @@ #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/gpu_tracer_vk.h" -#include "impeller/renderer/backend/vulkan/surface_vk.h" -#include "impeller/renderer/backend/vulkan/swapchain_image_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_surface_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_image_vk.h" #include "impeller/renderer/context.h" #include "vulkan/vulkan_structs.hpp" @@ -115,21 +115,21 @@ static std::optional ChooseAlphaCompositionMode( return std::nullopt; } -std::shared_ptr SwapchainImplVK::Create( +std::shared_ptr KHRSwapchainImplVK::Create( const std::shared_ptr& context, vk::UniqueSurfaceKHR surface, const ISize& size, bool enable_msaa, vk::SwapchainKHR old_swapchain) { - return std::shared_ptr(new SwapchainImplVK( + return std::shared_ptr(new KHRSwapchainImplVK( context, std::move(surface), size, enable_msaa, old_swapchain)); } -SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, - vk::UniqueSurfaceKHR surface, - const ISize& size, - bool enable_msaa, - vk::SwapchainKHR old_swapchain) { +KHRSwapchainImplVK::KHRSwapchainImplVK(const std::shared_ptr& context, + vk::UniqueSurfaceKHR surface, + const ISize& size, + bool enable_msaa, + vk::SwapchainKHR old_swapchain) { if (!context) { VALIDATION_LOG << "Cannot create a swapchain without a context."; return; @@ -228,13 +228,13 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, texture_desc.size = ISize::MakeWH(swapchain_info.imageExtent.width, swapchain_info.imageExtent.height); - std::vector> swapchain_images; + std::vector> swapchain_images; for (const auto& image : images) { - auto swapchain_image = - std::make_shared(texture_desc, // texture descriptor - vk_context.GetDevice(), // device - image // image - ); + auto swapchain_image = std::make_shared( + texture_desc, // texture descriptor + vk_context.GetDevice(), // device + image // image + ); if (!swapchain_image->IsValid()) { VALIDATION_LOG << "Could not create swapchain image."; return; @@ -273,19 +273,19 @@ SwapchainImplVK::SwapchainImplVK(const std::shared_ptr& context, is_valid_ = true; } -SwapchainImplVK::~SwapchainImplVK() { +KHRSwapchainImplVK::~KHRSwapchainImplVK() { DestroySwapchain(); } -const ISize& SwapchainImplVK::GetSize() const { +const ISize& KHRSwapchainImplVK::GetSize() const { return size_; } -bool SwapchainImplVK::IsValid() const { +bool KHRSwapchainImplVK::IsValid() const { return is_valid_; } -void SwapchainImplVK::WaitIdle() const { +void KHRSwapchainImplVK::WaitIdle() const { if (auto context = context_.lock()) { [[maybe_unused]] auto result = ContextVK::Cast(*context).GetDevice().waitIdle(); @@ -293,7 +293,7 @@ void SwapchainImplVK::WaitIdle() const { } std::pair -SwapchainImplVK::DestroySwapchain() { +KHRSwapchainImplVK::DestroySwapchain() { WaitIdle(); is_valid_ = false; synchronizers_.clear(); @@ -302,18 +302,18 @@ SwapchainImplVK::DestroySwapchain() { return {std::move(surface_), std::move(swapchain_)}; } -vk::Format SwapchainImplVK::GetSurfaceFormat() const { +vk::Format KHRSwapchainImplVK::GetSurfaceFormat() const { return surface_format_; } -std::shared_ptr SwapchainImplVK::GetContext() const { +std::shared_ptr KHRSwapchainImplVK::GetContext() const { return context_.lock(); } -SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() { +KHRSwapchainImplVK::AcquireResult KHRSwapchainImplVK::AcquireNextDrawable() { auto context_strong = context_.lock(); if (!context_strong) { - return SwapchainImplVK::AcquireResult{}; + return KHRSwapchainImplVK::AcquireResult{}; } const auto& context = ContextVK::Cast(*context_strong); @@ -327,7 +327,7 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() { /// if (!sync->WaitForFence(context.GetDevice())) { VALIDATION_LOG << "Could not wait for fence."; - return SwapchainImplVK::AcquireResult{}; + return KHRSwapchainImplVK::AcquireResult{}; } //---------------------------------------------------------------------------- @@ -358,7 +358,7 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() { if (index >= images_.size()) { VALIDATION_LOG << "Swapchain returned an invalid image index."; - return SwapchainImplVK::AcquireResult{}; + return KHRSwapchainImplVK::AcquireResult{}; } /// Record all subsequent cmd buffers as part of the current frame. @@ -366,7 +366,7 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() { auto image = images_[index % images_.size()]; uint32_t image_index = index; - return AcquireResult{SurfaceVK::WrapSwapchainImage( + return AcquireResult{KHRSurfaceVK::WrapSwapchainImage( context_strong, // context image, // swapchain image [weak_swapchain = weak_from_this(), image, image_index]() -> bool { @@ -380,8 +380,9 @@ SwapchainImplVK::AcquireResult SwapchainImplVK::AcquireNextDrawable() { )}; } -bool SwapchainImplVK::Present(const std::shared_ptr& image, - uint32_t index) { +bool KHRSwapchainImplVK::Present( + const std::shared_ptr& image, + uint32_t index) { auto context_strong = context_.lock(); if (!context_strong) { return false; diff --git a/impeller/renderer/backend/vulkan/swapchain_impl_vk.h b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h similarity index 67% rename from impeller/renderer/backend/vulkan/swapchain_impl_vk.h rename to impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h index 06f9d37610d52..72c16eaa5b995 100644 --- a/impeller/renderer/backend/vulkan/swapchain_impl_vk.h +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_IMPL_VK_H_ -#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_IMPL_VK_H_ +#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_IMPL_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_IMPL_VK_H_ #include #include @@ -16,7 +16,7 @@ namespace impeller { class Context; -class SwapchainImageVK; +class KHRSwapchainImageVK; class Surface; struct FrameSynchronizer; @@ -28,17 +28,17 @@ struct FrameSynchronizer; /// the caller must recreate another instance by optionally /// stealing this implementations guts. /// -class SwapchainImplVK final - : public std::enable_shared_from_this { +class KHRSwapchainImplVK final + : public std::enable_shared_from_this { public: - static std::shared_ptr Create( + static std::shared_ptr Create( const std::shared_ptr& context, vk::UniqueSurfaceKHR surface, const ISize& size, bool enable_msaa = true, vk::SwapchainKHR old_swapchain = VK_NULL_HANDLE); - ~SwapchainImplVK(); + ~KHRSwapchainImplVK(); bool IsValid() const; @@ -68,28 +68,29 @@ class SwapchainImplVK final vk::UniqueSurfaceKHR surface_; vk::Format surface_format_ = vk::Format::eUndefined; vk::UniqueSwapchainKHR swapchain_; - std::vector> images_; + std::vector> images_; std::vector> synchronizers_; size_t current_frame_ = 0u; ISize size_; bool enable_msaa_ = true; bool is_valid_ = false; - SwapchainImplVK(const std::shared_ptr& context, - vk::UniqueSurfaceKHR surface, - const ISize& size, - bool enable_msaa, - vk::SwapchainKHR old_swapchain); + KHRSwapchainImplVK(const std::shared_ptr& context, + vk::UniqueSurfaceKHR surface, + const ISize& size, + bool enable_msaa, + vk::SwapchainKHR old_swapchain); - bool Present(const std::shared_ptr& image, uint32_t index); + bool Present(const std::shared_ptr& image, + uint32_t index); void WaitIdle() const; - SwapchainImplVK(const SwapchainImplVK&) = delete; + KHRSwapchainImplVK(const KHRSwapchainImplVK&) = delete; - SwapchainImplVK& operator=(const SwapchainImplVK&) = delete; + KHRSwapchainImplVK& operator=(const KHRSwapchainImplVK&) = delete; }; } // namespace impeller -#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_IMPL_VK_H_ +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_IMPL_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.cc b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.cc new file mode 100644 index 0000000000000..a3ec1284786f1 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.cc @@ -0,0 +1,89 @@ +// 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 "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h" + +#include "flutter/fml/trace_event.h" +#include "impeller/base/validation.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.h" + +namespace impeller { + +std::shared_ptr KHRSwapchainVK::Create( + const std::shared_ptr& context, + vk::UniqueSurfaceKHR surface, + const ISize& size, + bool enable_msaa) { + auto impl = KHRSwapchainImplVK::Create(context, std::move(surface), size, + enable_msaa); + if (!impl || !impl->IsValid()) { + VALIDATION_LOG << "Failed to create SwapchainVK implementation."; + return nullptr; + } + return std::shared_ptr( + new KHRSwapchainVK(std::move(impl), size, enable_msaa)); +} + +KHRSwapchainVK::KHRSwapchainVK(std::shared_ptr impl, + const ISize& size, + bool enable_msaa) + : impl_(std::move(impl)), size_(size), enable_msaa_(enable_msaa) {} + +KHRSwapchainVK::~KHRSwapchainVK() = default; + +bool KHRSwapchainVK::IsValid() const { + return impl_ ? impl_->IsValid() : false; +} + +void KHRSwapchainVK::UpdateSurfaceSize(const ISize& size) { + // Update the size of the swapchain. On the next acquired drawable, + // the sizes may no longer match, forcing the swapchain to be recreated. + size_ = size; +} + +std::shared_ptr KHRSwapchainVK::AcquireNextDrawable() { + if (!IsValid()) { + return nullptr; + } + + TRACE_EVENT0("impeller", __FUNCTION__); + + auto result = impl_->AcquireNextDrawable(); + if (!result.out_of_date && size_ == impl_->GetSize()) { + return std::move(result.surface); + } + + TRACE_EVENT0("impeller", "RecreateSwapchain"); + + // This swapchain implementation indicates that it is out of date. Tear it + // down and make a new one. + auto context = impl_->GetContext(); + auto [surface, old_swapchain] = impl_->DestroySwapchain(); + + auto new_impl = KHRSwapchainImplVK::Create(context, // + std::move(surface), // + size_, // + enable_msaa_, // + *old_swapchain // + ); + if (!new_impl || !new_impl->IsValid()) { + VALIDATION_LOG << "Could not update swapchain."; + // The old swapchain is dead because we took its surface. This is + // unrecoverable. + impl_.reset(); + return nullptr; + } + impl_ = std::move(new_impl); + + //---------------------------------------------------------------------------- + /// We managed to recreate the swapchain in the new configuration. Try again. + /// + return AcquireNextDrawable(); +} + +vk::Format KHRSwapchainVK::GetSurfaceFormat() const { + return IsValid() ? impl_->GetSurfaceFormat() : vk::Format::eUndefined; +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h new file mode 100644 index 0000000000000..0d7031aca6489 --- /dev/null +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h @@ -0,0 +1,65 @@ +// 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_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_VK_H_ +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_VK_H_ + +#include + +#include "impeller/geometry/size.h" +#include "impeller/renderer/backend/vulkan/swapchain_vk.h" +#include "impeller/renderer/backend/vulkan/vk.h" +#include "impeller/renderer/context.h" +#include "impeller/renderer/surface.h" + +namespace impeller { + +class KHRSwapchainImplVK; + +//------------------------------------------------------------------------------ +/// @brief A swapchain that adapts to the underlying surface going out of +/// date. If the caller cannot acquire the next drawable, it is due +/// to an unrecoverable error and the swapchain must be recreated +/// with a new surface. +/// +class KHRSwapchainVK final : public SwapchainVK { + public: + static std::shared_ptr Create( + const std::shared_ptr& context, + vk::UniqueSurfaceKHR surface, + const ISize& size, + bool enable_msaa = true); + + // |SwapchainVK| + ~KHRSwapchainVK() override; + + // |SwapchainVK| + bool IsValid() const override; + + // |SwapchainVK| + vk::Format GetSurfaceFormat() const override; + + // |SwapchainVK| + std::shared_ptr AcquireNextDrawable() override; + + // |SwapchainVK| + void UpdateSurfaceSize(const ISize& size) override; + + private: + std::shared_ptr impl_; + ISize size_; + const bool enable_msaa_; + + KHRSwapchainVK(std::shared_ptr impl, + const ISize& size, + bool enable_msaa); + + KHRSwapchainVK(const KHRSwapchainVK&) = delete; + + KHRSwapchainVK& operator=(const KHRSwapchainVK&) = delete; +}; + +} // namespace impeller + +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_KHR_KHR_SWAPCHAIN_VK_H_ diff --git a/impeller/renderer/backend/vulkan/swapchain_vk.cc b/impeller/renderer/backend/vulkan/swapchain_vk.cc index 22dc195ebfdb8..2fd945eae9e21 100644 --- a/impeller/renderer/backend/vulkan/swapchain_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain_vk.cc @@ -4,86 +4,10 @@ #include "impeller/renderer/backend/vulkan/swapchain_vk.h" -#include "flutter/fml/trace_event.h" -#include "impeller/base/validation.h" -#include "impeller/renderer/backend/vulkan/swapchain_impl_vk.h" - namespace impeller { -std::shared_ptr SwapchainVK::Create( - const std::shared_ptr& context, - vk::UniqueSurfaceKHR surface, - const ISize& size, - bool enable_msaa) { - auto impl = - SwapchainImplVK::Create(context, std::move(surface), size, enable_msaa); - if (!impl || !impl->IsValid()) { - VALIDATION_LOG << "Failed to create SwapchainVK implementation."; - return nullptr; - } - return std::shared_ptr( - new SwapchainVK(std::move(impl), size, enable_msaa)); -} - -SwapchainVK::SwapchainVK(std::shared_ptr impl, - const ISize& size, - bool enable_msaa) - : impl_(std::move(impl)), size_(size), enable_msaa_(enable_msaa) {} +SwapchainVK::SwapchainVK() = default; SwapchainVK::~SwapchainVK() = default; -bool SwapchainVK::IsValid() const { - return impl_ ? impl_->IsValid() : false; -} - -void SwapchainVK::UpdateSurfaceSize(const ISize& size) { - // Update the size of the swapchain. On the next acquired drawable, - // the sizes may no longer match, forcing the swapchain to be recreated. - size_ = size; -} - -std::unique_ptr SwapchainVK::AcquireNextDrawable() { - if (!IsValid()) { - return nullptr; - } - - TRACE_EVENT0("impeller", __FUNCTION__); - - auto result = impl_->AcquireNextDrawable(); - if (!result.out_of_date && size_ == impl_->GetSize()) { - return std::move(result.surface); - } - - TRACE_EVENT0("impeller", "RecreateSwapchain"); - - // This swapchain implementation indicates that it is out of date. Tear it - // down and make a new one. - auto context = impl_->GetContext(); - auto [surface, old_swapchain] = impl_->DestroySwapchain(); - - auto new_impl = SwapchainImplVK::Create(context, // - std::move(surface), // - size_, // - enable_msaa_, // - *old_swapchain // - ); - if (!new_impl || !new_impl->IsValid()) { - VALIDATION_LOG << "Could not update swapchain."; - // The old swapchain is dead because we took its surface. This is - // unrecoverable. - impl_.reset(); - return nullptr; - } - impl_ = std::move(new_impl); - - //---------------------------------------------------------------------------- - /// We managed to recreate the swapchain in the new configuration. Try again. - /// - return AcquireNextDrawable(); -} - -vk::Format SwapchainVK::GetSurfaceFormat() const { - return IsValid() ? impl_->GetSurfaceFormat() : vk::Format::eUndefined; -} - } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/swapchain_vk.h b/impeller/renderer/backend/vulkan/swapchain_vk.h index 1f02f1cd606dd..1d5074ae947b0 100644 --- a/impeller/renderer/backend/vulkan/swapchain_vk.h +++ b/impeller/renderer/backend/vulkan/swapchain_vk.h @@ -5,55 +5,59 @@ #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_VK_H_ #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_SWAPCHAIN_VK_H_ -#include - -#include "impeller/geometry/size.h" #include "impeller/renderer/backend/vulkan/vk.h" -#include "impeller/renderer/context.h" #include "impeller/renderer/surface.h" namespace impeller { -class SwapchainImplVK; - //------------------------------------------------------------------------------ -/// @brief A swapchain that adapts to the underlying surface going out of -/// date. If the caller cannot acquire the next drawable, it is due -/// to an unrecoverable error and the swapchain must be recreated -/// with a new surface. +/// @brief A collection of surfaces shared with the system compositor to +/// present images in the windowing system on the target platform. /// class SwapchainVK { public: - static std::shared_ptr Create( - const std::shared_ptr& context, - vk::UniqueSurfaceKHR surface, - const ISize& size, - bool enable_msaa = true); - - ~SwapchainVK(); - - bool IsValid() const; - - std::unique_ptr AcquireNextDrawable(); + SwapchainVK(); - vk::Format GetSurfaceFormat() const; - - /// @brief Mark the current swapchain configuration as dirty, forcing it to be - /// recreated on the next frame. - void UpdateSurfaceSize(const ISize& size); - - private: - std::shared_ptr impl_; - ISize size_; - const bool enable_msaa_; - - SwapchainVK(std::shared_ptr impl, - const ISize& size, - bool enable_msaa); + virtual ~SwapchainVK(); SwapchainVK(const SwapchainVK&) = delete; SwapchainVK& operator=(const SwapchainVK&) = delete; + + //---------------------------------------------------------------------------- + /// @brief If this instance of the swapchain is currently valid or must + /// be discarded. + /// + /// @return True if valid, False otherwise. + /// + virtual bool IsValid() const = 0; + + //---------------------------------------------------------------------------- + /// @brief The format of the images in this swapchain. + /// + /// @return The format. + /// + virtual vk::Format GetSurfaceFormat() const = 0; + + //---------------------------------------------------------------------------- + /// @brief Acquire the next swapchain image as a fully configured surface + /// to draw into. + /// + /// This might be a blocking call as the swapchain may need to + /// wait for the image to become available after the compositor is + /// done using it. + /// + /// @return The next swapchain image. + /// + virtual std::shared_ptr AcquireNextDrawable() = 0; + + //---------------------------------------------------------------------------- + /// @brief Mark the current swapchain configuration as dirty, forcing it + /// to be recreated on the next frame. + /// + /// @param[in] size The new surface size in pixels + /// + virtual void UpdateSurfaceSize(const ISize& size) = 0; }; } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc b/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc index a78d3187b58df..4b89f01d845d0 100644 --- a/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc +++ b/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc @@ -4,7 +4,7 @@ #include "flutter/testing/testing.h" // IWYU pragma: keep #include "gtest/gtest.h" -#include "impeller/renderer/backend/vulkan/swapchain_vk.h" +#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h" #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h" #include "vulkan/vulkan_enums.hpp" @@ -28,7 +28,7 @@ TEST(SwapchainTest, CanCreateSwapchain) { auto surface = CreateSurface(*context); auto swapchain = - SwapchainVK::Create(context, std::move(surface), ISize{1, 1}); + KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1}); EXPECT_TRUE(swapchain->IsValid()); } @@ -38,8 +38,9 @@ TEST(SwapchainTest, RecreateSwapchainWhenSizeChanges) { auto surface = CreateSurface(*context); SetSwapchainImageSize(ISize{1, 1}); - auto swapchain = SwapchainVK::Create(context, std::move(surface), ISize{1, 1}, - /*enable_msaa=*/false); + auto swapchain = + KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1}, + /*enable_msaa=*/false); auto image = swapchain->AcquireNextDrawable(); auto expected_size = ISize{1, 1}; EXPECT_EQ(image->GetSize(), expected_size); diff --git a/impeller/renderer/renderer.cc b/impeller/renderer/renderer.cc index abc5dc2b7ce75..0dd2e3d1d4e93 100644 --- a/impeller/renderer/renderer.cc +++ b/impeller/renderer/renderer.cc @@ -30,7 +30,7 @@ bool Renderer::IsValid() const { return is_valid_; } -bool Renderer::Render(std::unique_ptr surface, +bool Renderer::Render(const std::shared_ptr& surface, const RenderCallback& render_callback) const { TRACE_EVENT0("impeller", "Renderer::Render"); if (!IsValid()) { diff --git a/impeller/renderer/renderer.h b/impeller/renderer/renderer.h index 1a07e59dcd02f..0709a21c12cf6 100644 --- a/impeller/renderer/renderer.h +++ b/impeller/renderer/renderer.h @@ -29,7 +29,7 @@ class Renderer { bool IsValid() const; - bool Render(std::unique_ptr surface, + bool Render(const std::shared_ptr& surface, const RenderCallback& callback) const; std::shared_ptr GetContext() const; diff --git a/impeller/renderer/surface.cc b/impeller/renderer/surface.cc index ce38697f4726a..2c6b01015b4e7 100644 --- a/impeller/renderer/surface.cc +++ b/impeller/renderer/surface.cc @@ -34,7 +34,7 @@ const RenderTarget& Surface::GetTargetRenderPassDescriptor() const { return desc_; } -bool Surface::Present() const { +bool Surface::Present() { return false; }; diff --git a/impeller/renderer/surface.h b/impeller/renderer/surface.h index e0e4abe5faa5f..b2e7801cffb53 100644 --- a/impeller/renderer/surface.h +++ b/impeller/renderer/surface.h @@ -29,7 +29,7 @@ class Surface { const RenderTarget& GetTargetRenderPassDescriptor() const; - virtual bool Present() const; + virtual bool Present(); private: RenderTarget desc_; diff --git a/impeller/toolkit/android/BUILD.gn b/impeller/toolkit/android/BUILD.gn new file mode 100644 index 0000000000000..b04f3e6c75504 --- /dev/null +++ b/impeller/toolkit/android/BUILD.gn @@ -0,0 +1,26 @@ +# 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. + +import("../../tools/impeller.gni") + +impeller_component("android") { + sources = [ + "hardware_buffer.cc", + "hardware_buffer.h", + "native_window.cc", + "native_window.h", + "proc_table.cc", + "proc_table.h", + "surface_control.cc", + "surface_control.h", + "surface_transaction.cc", + "surface_transaction.h", + ] + + public_deps = [ + "../../base", + "../../geometry", + "//flutter/fml", + ] +} diff --git a/impeller/toolkit/android/hardware_buffer.cc b/impeller/toolkit/android/hardware_buffer.cc new file mode 100644 index 0000000000000..78f12309c7678 --- /dev/null +++ b/impeller/toolkit/android/hardware_buffer.cc @@ -0,0 +1,100 @@ +// 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 "impeller/toolkit/android/hardware_buffer.h" + +#include "impeller/base/validation.h" + +namespace impeller::android { + +static AHardwareBuffer_Format ToAHardwareBufferFormat( + HardwareBufferFormat format) { + switch (format) { + case HardwareBufferFormat::kR8G8B8A8UNormInt: + return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; + } + FML_UNREACHABLE(); +} + +static AHardwareBuffer_Desc ToAHardwareBufferDesc( + const HardwareBufferDescriptor& desc) { + AHardwareBuffer_Desc ahb_desc = {}; + ahb_desc.width = desc.size.width; + ahb_desc.height = desc.size.height; + ahb_desc.format = ToAHardwareBufferFormat(desc.format); + ahb_desc.layers = 1u; + if (desc.usage & static_cast( + HardwareBufferUsageFlags::kFrameBufferAttachment)) { + ahb_desc.usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; + } + if (desc.usage & static_cast( + HardwareBufferUsageFlags::kCompositorOverlay)) { + ahb_desc.usage |= AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY; + } + if (desc.usage & static_cast( + HardwareBufferUsageFlags::kSampledImage)) { + ahb_desc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + } + return ahb_desc; +} + +bool HardwareBufferDescriptor::IsAllocatable() const { + const auto desc = ToAHardwareBufferDesc(*this); + return GetProcTable().AHardwareBuffer_isSupported(&desc) != 0u; +} + +HardwareBuffer::HardwareBuffer(HardwareBufferDescriptor descriptor) + : descriptor_(descriptor), + android_descriptor_(ToAHardwareBufferDesc(descriptor_)) { + if (!descriptor_.IsAllocatable()) { + VALIDATION_LOG << "The hardware buffer descriptor is not allocatable."; + return; + } + const auto& proc_table = GetProcTable(); + + AHardwareBuffer* buffer = nullptr; + if (auto result = + proc_table.AHardwareBuffer_allocate(&android_descriptor_, &buffer); + result != 0 || buffer == nullptr) { + VALIDATION_LOG << "Could not allocate hardware buffer. Error: " << result; + return; + } + buffer_.reset(buffer); + is_valid_ = true; +} + +HardwareBuffer::~HardwareBuffer() = default; + +bool HardwareBuffer::IsValid() const { + return is_valid_; +} + +AHardwareBuffer* HardwareBuffer::GetHandle() const { + return buffer_.get(); +} + +HardwareBufferDescriptor HardwareBufferDescriptor::MakeForSwapchainImage( + ISize size) { + HardwareBufferDescriptor desc; + desc.format = HardwareBufferFormat::kR8G8B8A8UNormInt; + // Zero sized hardware buffers cannot be allocated. + desc.size = size.Max(ISize{1u, 1u}); + desc.usage = + static_cast( + HardwareBufferUsageFlags::kFrameBufferAttachment) | + static_cast( + HardwareBufferUsageFlags::kCompositorOverlay) | + static_cast(HardwareBufferUsageFlags::kSampledImage); + return desc; +} + +const HardwareBufferDescriptor& HardwareBuffer::GetDescriptor() const { + return descriptor_; +} + +const AHardwareBuffer_Desc& HardwareBuffer::GetAndroidDescriptor() const { + return android_descriptor_; +} + +} // namespace impeller::android diff --git a/impeller/toolkit/android/hardware_buffer.h b/impeller/toolkit/android/hardware_buffer.h new file mode 100644 index 0000000000000..46d44cf67b344 --- /dev/null +++ b/impeller/toolkit/android/hardware_buffer.h @@ -0,0 +1,98 @@ +// 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_IMPELLER_TOOLKIT_ANDROID_HARDWARE_BUFFER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_ANDROID_HARDWARE_BUFFER_H_ + +#include "flutter/fml/unique_object.h" +#include "impeller/geometry/size.h" +#include "impeller/toolkit/android/proc_table.h" + +namespace impeller::android { + +enum class HardwareBufferFormat { + //---------------------------------------------------------------------------- + /// This format is guaranteed to be supported on all versions of Android. + /// + /// Why have many format when one format do trick. + /// + kR8G8B8A8UNormInt, +}; + +using HardwareBufferUsage = uint8_t; + +enum class HardwareBufferUsageFlags : HardwareBufferUsage { + kFrameBufferAttachment = 1u << 0u, + kCompositorOverlay = 1u << 1u, + kSampledImage = 1u << 2u, +}; + +struct HardwareBufferDescriptor { + HardwareBufferFormat format = HardwareBufferFormat::kR8G8B8A8UNormInt; + ISize size; + HardwareBufferUsage usage = 0u; + + static HardwareBufferDescriptor MakeForSwapchainImage(ISize size); + + bool IsAllocatable() const; + + constexpr bool operator==(const HardwareBufferDescriptor& o) const { + return format == o.format && size == o.size && usage == o.usage; + } + + constexpr bool operator!=(const HardwareBufferDescriptor& o) const { + return !(*this == o); + } +}; + +//------------------------------------------------------------------------------ +/// @brief A wrapper for AHardwareBuffer +/// https://developer.android.com/ndk/reference/group/a-hardware-buffer +/// +/// This wrapper creates and owns a handle to a managed hardware +/// buffer. That is, there is no ability to take a reference to an +/// externally created hardware buffer. +/// +/// This wrapper is only available on Android API 29 and above. +/// +class HardwareBuffer { + public: + explicit HardwareBuffer(HardwareBufferDescriptor descriptor); + + ~HardwareBuffer(); + + HardwareBuffer(const HardwareBuffer&) = delete; + + HardwareBuffer& operator=(const HardwareBuffer&) = delete; + + bool IsValid() const; + + AHardwareBuffer* GetHandle() const; + + const HardwareBufferDescriptor& GetDescriptor() const; + + const AHardwareBuffer_Desc& GetAndroidDescriptor() const; + + private: + struct UniqueAHardwareBufferTraits { + static AHardwareBuffer* InvalidValue() { return nullptr; } + + static bool IsValid(AHardwareBuffer* value) { + return value != InvalidValue(); + } + + static void Free(AHardwareBuffer* value) { + GetProcTable().AHardwareBuffer_release(value); + } + }; + + const HardwareBufferDescriptor descriptor_; + const AHardwareBuffer_Desc android_descriptor_; + fml::UniqueObject buffer_; + bool is_valid_ = false; +}; + +} // namespace impeller::android + +#endif // FLUTTER_IMPELLER_TOOLKIT_ANDROID_HARDWARE_BUFFER_H_ diff --git a/impeller/toolkit/android/native_window.cc b/impeller/toolkit/android/native_window.cc new file mode 100644 index 0000000000000..663a482f624a3 --- /dev/null +++ b/impeller/toolkit/android/native_window.cc @@ -0,0 +1,34 @@ +// 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 "impeller/toolkit/android/native_window.h" + +namespace impeller::android { + +NativeWindow::NativeWindow(ANativeWindow* window) : window_(window) { + if (window_.get()) { + GetProcTable().ANativeWindow_acquire(window_.get()); + } +} + +NativeWindow::~NativeWindow() = default; + +bool NativeWindow::IsValid() const { + return window_.is_valid(); +} + +ISize NativeWindow::GetSize() const { + if (!IsValid()) { + return {}; + } + const int32_t width = ANativeWindow_getWidth(window_.get()); + const int32_t height = ANativeWindow_getHeight(window_.get()); + return ISize::MakeWH(std::max(width, 0), std::max(height, 0)); +} + +ANativeWindow* NativeWindow::GetHandle() const { + return window_.get(); +} + +} // namespace impeller::android diff --git a/impeller/toolkit/android/native_window.h b/impeller/toolkit/android/native_window.h new file mode 100644 index 0000000000000..44b1c648b7580 --- /dev/null +++ b/impeller/toolkit/android/native_window.h @@ -0,0 +1,57 @@ +// 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_IMPELLER_TOOLKIT_ANDROID_NATIVE_WINDOW_H_ +#define FLUTTER_IMPELLER_TOOLKIT_ANDROID_NATIVE_WINDOW_H_ + +#include "flutter/fml/unique_object.h" +#include "impeller/geometry/size.h" +#include "impeller/toolkit/android/proc_table.h" + +namespace impeller::android { + +//------------------------------------------------------------------------------ +/// @brief A wrapper for ANativeWindow +/// https://developer.android.com/ndk/reference/group/a-native-window +/// +/// This wrapper is only available on Android. +/// +class NativeWindow { + public: + explicit NativeWindow(ANativeWindow* window); + + ~NativeWindow(); + + NativeWindow(const NativeWindow&) = delete; + + NativeWindow& operator=(const NativeWindow&) = delete; + + bool IsValid() const; + + //---------------------------------------------------------------------------- + /// @return The current of the native window. + /// + ISize GetSize() const; + + ANativeWindow* GetHandle() const; + + private: + struct UniqueANativeWindowTraits { + static ANativeWindow* InvalidValue() { return nullptr; } + + static bool IsValid(ANativeWindow* value) { + return value != InvalidValue(); + } + + static void Free(ANativeWindow* value) { + GetProcTable().ANativeWindow_release(value); + } + }; + + fml::UniqueObject window_; +}; + +} // namespace impeller::android + +#endif // FLUTTER_IMPELLER_TOOLKIT_ANDROID_NATIVE_WINDOW_H_ diff --git a/impeller/toolkit/android/proc_table.cc b/impeller/toolkit/android/proc_table.cc new file mode 100644 index 0000000000000..f56c7100cce10 --- /dev/null +++ b/impeller/toolkit/android/proc_table.cc @@ -0,0 +1,46 @@ +// 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/impeller/toolkit/android/proc_table.h" + +#include "impeller/base/validation.h" + +namespace impeller::android { + +const ProcTable& GetProcTable() { + static ProcTable gProcTable; + return gProcTable; +} + +ProcTable::ProcTable() + : lib_android_(fml::NativeLibrary::Create("libandroid.so")) { + if (!lib_android_) { + VALIDATION_LOG << "Could not open libandroid.so"; + return; + } + +#define RESOLVE_PROC(table_member, api) \ + { \ + auto resolved = \ + lib_android_->ResolveFunction( \ + table_member.proc_name); \ + if (!resolved.has_value()) { \ + VALIDATION_LOG << "Could not resolve function: " \ + << table_member.proc_name; \ + return; \ + } \ + table_member.proc = resolved.value(); \ + } + FOR_EACH_ANDROID_PROC(RESOLVE_PROC); +#undef RESOLVE_PROC + is_valid_ = true; +} + +ProcTable::~ProcTable() = default; + +bool ProcTable::IsValid() { + return is_valid_; +} + +} // namespace impeller::android diff --git a/impeller/toolkit/android/proc_table.h b/impeller/toolkit/android/proc_table.h new file mode 100644 index 0000000000000..b64feb8be0c20 --- /dev/null +++ b/impeller/toolkit/android/proc_table.h @@ -0,0 +1,79 @@ +// 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_IMPELLER_TOOLKIT_ANDROID_PROC_TABLE_H_ +#define FLUTTER_IMPELLER_TOOLKIT_ANDROID_PROC_TABLE_H_ + +#include +#include + +#include + +#include "flutter/fml/native_library.h" + +namespace impeller::android { + +#define FOR_EACH_ANDROID_PROC(INVOKE) \ + INVOKE(AHardwareBuffer_allocate, 26) \ + INVOKE(AHardwareBuffer_acquire, 26) \ + INVOKE(AHardwareBuffer_release, 26) \ + INVOKE(AHardwareBuffer_isSupported, 29) \ + INVOKE(AHardwareBuffer_describe, 26) \ + INVOKE(ANativeWindow_acquire, 0) \ + INVOKE(ANativeWindow_release, 0) \ + INVOKE(ANativeWindow_getWidth, 0) \ + INVOKE(ANativeWindow_getHeight, 0) \ + INVOKE(ASurfaceControl_createFromWindow, 29) \ + INVOKE(ASurfaceControl_release, 29) \ + INVOKE(ASurfaceTransaction_create, 29) \ + INVOKE(ASurfaceTransaction_delete, 29) \ + INVOKE(ASurfaceTransaction_apply, 29) \ + INVOKE(ASurfaceTransaction_setOnComplete, 29) \ + INVOKE(ASurfaceTransaction_reparent, 29) \ + INVOKE(ASurfaceTransaction_setBuffer, 29) \ + INVOKE(ASurfaceTransaction_setColor, 29) + +template +struct AndroidProc { + using AndroidProcType = T; + + const char* proc_name = nullptr; + + size_t api_availability = 0; + + AndroidProcType* proc = nullptr; + + template + auto operator()(Args&&... args) const { + return proc(std::forward(args)...); + } +}; + +struct ProcTable { +#define DEFINE_PROC(name, api) \ + AndroidProc name = {.proc_name = #name, \ + .api_availability = api}; + FOR_EACH_ANDROID_PROC(DEFINE_PROC); +#undef DEFINE_PROC + + ProcTable(); + + ~ProcTable(); + + ProcTable(const ProcTable&) = delete; + + ProcTable& operator=(const ProcTable&) = delete; + + bool IsValid(); + + private: + fml::RefPtr lib_android_; + bool is_valid_ = false; +}; + +const ProcTable& GetProcTable(); + +} // namespace impeller::android + +#endif // FLUTTER_IMPELLER_TOOLKIT_ANDROID_PROC_TABLE_H_ diff --git a/impeller/toolkit/android/surface_control.cc b/impeller/toolkit/android/surface_control.cc new file mode 100644 index 0000000000000..af173ead8da52 --- /dev/null +++ b/impeller/toolkit/android/surface_control.cc @@ -0,0 +1,43 @@ +// 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 "impeller/toolkit/android/surface_control.h" + +#include "impeller/base/validation.h" +#include "impeller/toolkit/android/surface_transaction.h" + +namespace impeller::android { + +SurfaceControl::SurfaceControl(ANativeWindow* window, const char* debug_name) + : control_(GetProcTable().ASurfaceControl_createFromWindow( + window, + debug_name == nullptr ? "Impeller Layer" : debug_name)) {} + +SurfaceControl::~SurfaceControl() { + if (!RemoveFromParent()) { + VALIDATION_LOG << "Surface control could not be removed from its parent. " + "Expect a leak."; + } +} + +bool SurfaceControl::IsValid() const { + return control_.is_valid(); +} + +ASurfaceControl* SurfaceControl::GetHandle() const { + return control_.get(); +} + +bool SurfaceControl::RemoveFromParent() const { + if (!IsValid()) { + return false; + } + SurfaceTransaction transaction; + if (!transaction.SetParent(*this, nullptr)) { + return false; + } + return transaction.Apply(); +} + +} // namespace impeller::android diff --git a/impeller/toolkit/android/surface_control.h b/impeller/toolkit/android/surface_control.h new file mode 100644 index 0000000000000..88800260bcff0 --- /dev/null +++ b/impeller/toolkit/android/surface_control.h @@ -0,0 +1,80 @@ +// 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_IMPELLER_TOOLKIT_ANDROID_SURFACE_CONTROL_H_ +#define FLUTTER_IMPELLER_TOOLKIT_ANDROID_SURFACE_CONTROL_H_ + +#include "flutter/fml/unique_object.h" +#include "impeller/toolkit/android/proc_table.h" + +namespace impeller::android { + +//------------------------------------------------------------------------------ +/// @brief A wrapper for ASurfaceControl. +/// https://developer.android.com/ndk/reference/group/native-activity#asurfacecontrol +/// +/// Instances of this class represent a node in the hierarchy of +/// surfaces sent to the system compositor for final composition. +/// +/// This wrapper is only available on Android API 29 and above. +/// +class SurfaceControl { + public: + //---------------------------------------------------------------------------- + /// @brief Creates a new surface control and adds it as a child of the + /// given window. + /// + /// @param window The window + /// @param[in] debug_name A debug name. See it using + /// `adb shell dumpsys SurfaceFlinger` along with + /// other control properties. If no debug name is + /// specified, the value "Impeller Layer" is used. + /// + explicit SurfaceControl(ANativeWindow* window, + const char* debug_name = nullptr); + + //---------------------------------------------------------------------------- + /// @brief Removes the surface control from the presentation hierarchy + /// managed by the system compositor and release the client side + /// reference to the control. At this point, it may be collected + /// when the compositor is also done using it. + /// + ~SurfaceControl(); + + SurfaceControl(const SurfaceControl&) = delete; + + SurfaceControl& operator=(const SurfaceControl&) = delete; + + bool IsValid() const; + + ASurfaceControl* GetHandle() const; + + //---------------------------------------------------------------------------- + /// @brief Remove the surface control from the hierarchy of nodes + /// presented by the system compositor. + /// + /// @return `true` If the control will be removed from the hierarchy of + /// nodes presented by the system compositor. + /// + bool RemoveFromParent() const; + + private: + struct UniqueASurfaceControlTraits { + static ASurfaceControl* InvalidValue() { return nullptr; } + + static bool IsValid(ASurfaceControl* value) { + return value != InvalidValue(); + } + + static void Free(ASurfaceControl* value) { + GetProcTable().ASurfaceControl_release(value); + } + }; + + fml::UniqueObject control_; +}; + +} // namespace impeller::android + +#endif // FLUTTER_IMPELLER_TOOLKIT_ANDROID_SURFACE_CONTROL_H_ diff --git a/impeller/toolkit/android/surface_transaction.cc b/impeller/toolkit/android/surface_transaction.cc new file mode 100644 index 0000000000000..e5dcc39ec0108 --- /dev/null +++ b/impeller/toolkit/android/surface_transaction.cc @@ -0,0 +1,99 @@ +// 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/impeller/toolkit/android/surface_transaction.h" + +#include "flutter/impeller/toolkit/android/hardware_buffer.h" +#include "flutter/impeller/toolkit/android/surface_control.h" +#include "impeller/base/validation.h" + +namespace impeller::android { + +SurfaceTransaction::SurfaceTransaction() + : transaction_(GetProcTable().ASurfaceTransaction_create()) {} + +SurfaceTransaction::~SurfaceTransaction() = default; + +bool SurfaceTransaction::IsValid() const { + return transaction_.is_valid(); +} + +struct TransactionInFlightData { + SurfaceTransaction::OnCompleteCallback callback; +}; + +bool SurfaceTransaction::Apply(OnCompleteCallback callback) { + if (!IsValid()) { + return false; + } + + if (!callback) { + callback = []() {}; + } + + const auto& proc_table = GetProcTable(); + + auto data = std::make_unique(); + data->callback = callback; + proc_table.ASurfaceTransaction_setOnComplete( + transaction_.get(), // + data.release(), // + [](void* context, ASurfaceTransactionStats* stats) -> void { + auto data = reinterpret_cast(context); + data->callback(); + delete data; + }); + proc_table.ASurfaceTransaction_apply(transaction_.get()); + + // Transactions may not be applied over and over. + transaction_.reset(); + return true; +} + +bool SurfaceTransaction::SetContents(const SurfaceControl* control, + const HardwareBuffer* buffer) { + if (control == nullptr || buffer == nullptr) { + VALIDATION_LOG << "Invalid control or buffer."; + return false; + } + GetProcTable().ASurfaceTransaction_setBuffer(transaction_.get(), // + control->GetHandle(), // + buffer->GetHandle(), // + -1); + return true; +} + +bool SurfaceTransaction::SetBackgroundColor(const SurfaceControl& control, + const Color& color) { + if (!IsValid() || !control.IsValid()) { + return false; + } + GetProcTable().ASurfaceTransaction_setColor(transaction_.get(), // + control.GetHandle(), // + color.red, // + color.green, // + color.blue, // + color.alpha, // + ADATASPACE_SRGB_LINEAR // + ); + return true; +} + +bool SurfaceTransaction::SetParent(const SurfaceControl& control, + const SurfaceControl* new_parent) { + if (!IsValid() || !control.IsValid()) { + return false; + } + if (new_parent && !new_parent->IsValid()) { + return false; + } + GetProcTable().ASurfaceTransaction_reparent( + transaction_.get(), // + control.GetHandle(), // + new_parent == nullptr ? nullptr : new_parent->GetHandle() // + ); + return true; +} + +} // namespace impeller::android diff --git a/impeller/toolkit/android/surface_transaction.h b/impeller/toolkit/android/surface_transaction.h new file mode 100644 index 0000000000000..721e07a7adb3d --- /dev/null +++ b/impeller/toolkit/android/surface_transaction.h @@ -0,0 +1,125 @@ +// 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_IMPELLER_TOOLKIT_ANDROID_SURFACE_TRANSACTION_H_ +#define FLUTTER_IMPELLER_TOOLKIT_ANDROID_SURFACE_TRANSACTION_H_ + +#include +#include + +#include "flutter/fml/unique_object.h" +#include "impeller/geometry/color.h" +#include "impeller/toolkit/android/proc_table.h" + +namespace impeller::android { + +class SurfaceControl; +class HardwareBuffer; + +//------------------------------------------------------------------------------ +/// @brief A wrapper for ASurfaceTransaction. +/// https://developer.android.com/ndk/reference/group/native-activity#asurfacetransaction +/// +/// A surface transaction is a collection of updates to the +/// hierarchy of surfaces (represented by `ASurfaceControl` +/// instances) that are applied atomically in the compositor. +/// +/// This wrapper is only available on Android API 29 and above. +/// +class SurfaceTransaction { + public: + SurfaceTransaction(); + + ~SurfaceTransaction(); + + SurfaceTransaction(const SurfaceTransaction&) = delete; + + SurfaceTransaction& operator=(const SurfaceTransaction&) = delete; + + bool IsValid() const; + + //---------------------------------------------------------------------------- + /// @brief Encodes that the updated contents of a surface control are + /// specified by the given hardware buffer. The update will not be + /// committed till the call to `Apply` however. + /// + /// @see `SurfaceTransaction::Apply`. + /// + /// @param[in] control The control + /// @param[in] buffer The hardware buffer + /// + /// @return If the update was encoded in the transaction. + /// + [[nodiscard]] bool SetContents(const SurfaceControl* control, + const HardwareBuffer* buffer); + + //---------------------------------------------------------------------------- + /// @brief Encodes the updated background color of the surface control. + /// The update will not be committed till the call to `Apply` + /// however. + /// + /// @see `SurfaceTransaction::Apply`. + /// + /// @param[in] control The control + /// @param[in] color The color + /// + /// @return `true` if the background control will be set when transaction + /// is applied. + /// + [[nodiscard]] bool SetBackgroundColor(const SurfaceControl& control, + const Color& color); + + using OnCompleteCallback = std::function; + + //---------------------------------------------------------------------------- + /// @brief Applies the updated encoded in the transaction and invokes the + /// callback when the updated are complete. + /// + /// @warning The callback will be invoked on a system managed thread. + /// + /// @note It is fine to immediately destroy the transaction after the + /// call to apply. It is not necessary to wait for transaction + /// completion to collect the transaction handle. + /// + /// @param[in] callback The callback + /// + /// @return `true` if the surface transaction was applied. `true` does not + /// indicate the application was completed however. Only the + /// invocation of the callback denotes transaction completion. + /// + [[nodiscard]] bool Apply(OnCompleteCallback callback = nullptr); + + //---------------------------------------------------------------------------- + /// @brief Set the new parent control of the given control. If the new + /// parent is null, it is removed from the control hierarchy. + /// + /// @param[in] control The control + /// @param[in] new_parent The new parent + /// + /// @return `true` if the control will be re-parented when the transaction + /// is applied. + /// + [[nodiscard]] bool SetParent(const SurfaceControl& control, + const SurfaceControl* new_parent = nullptr); + + private: + struct UniqueASurfaceTransactionTraits { + static ASurfaceTransaction* InvalidValue() { return nullptr; } + + static bool IsValid(ASurfaceTransaction* value) { + return value != InvalidValue(); + } + + static void Free(ASurfaceTransaction* value) { + GetProcTable().ASurfaceTransaction_delete(value); + } + }; + + fml::UniqueObject + transaction_; +}; + +} // namespace impeller::android + +#endif // FLUTTER_IMPELLER_TOOLKIT_ANDROID_SURFACE_TRANSACTION_H_ diff --git a/shell/gpu/gpu_surface_vulkan_impeller.cc b/shell/gpu/gpu_surface_vulkan_impeller.cc index cf2733baab5ea..2620611e1a72e 100644 --- a/shell/gpu/gpu_surface_vulkan_impeller.cc +++ b/shell/gpu/gpu_surface_vulkan_impeller.cc @@ -58,7 +58,7 @@ std::unique_ptr GPUSurfaceVulkanImpeller::AcquireFrame( } auto& context_vk = impeller::SurfaceContextVK::Cast(*impeller_context_); - std::unique_ptr surface = context_vk.AcquireNextSurface(); + std::shared_ptr surface = context_vk.AcquireNextSurface(); if (!surface) { FML_LOG(ERROR) << "No surface available."; @@ -69,7 +69,7 @@ std::unique_ptr GPUSurfaceVulkanImpeller::AcquireFrame( fml::MakeCopyable([renderer = impeller_renderer_, // aiks_context = aiks_context_, // surface = std::move(surface) // - ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool { + ](SurfaceFrame& surface_frame, DlCanvas* canvas) -> bool { if (!aiks_context) { return false; } @@ -90,13 +90,13 @@ std::unique_ptr GPUSurfaceVulkanImpeller::AcquireFrame( 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, - /*reset_host_buffer=*/true); - })); + surface, fml::MakeCopyable( + [aiks_context, picture = std::move(picture)]( + impeller::RenderTarget& render_target) -> bool { + return aiks_context->Render( + picture, render_target, + /*reset_host_buffer=*/true); + })); }); return std::make_unique( diff --git a/shell/platform/android/android_surface_vulkan_impeller.cc b/shell/platform/android/android_surface_vulkan_impeller.cc index 2082d7fef8489..4a76900bd56ee 100644 --- a/shell/platform/android/android_surface_vulkan_impeller.cc +++ b/shell/platform/android/android_surface_vulkan_impeller.cc @@ -72,22 +72,9 @@ bool AndroidSurfaceVulkanImpeller::ResourceContextClearCurrent() { bool AndroidSurfaceVulkanImpeller::SetNativeWindow( fml::RefPtr window) { native_window_ = std::move(window); - bool success = native_window_ && native_window_->IsValid(); - if (success) { - auto surface = - surface_context_vk_->CreateAndroidSurface(native_window_->handle()); - - if (!surface) { - FML_LOG(ERROR) << "Could not create a vulkan surface."; - return false; - } - auto size = native_window_->GetSize(); - return surface_context_vk_->SetWindowSurface( - std::move(surface), impeller::ISize{size.width(), size.height()}); - } - - native_window_ = nullptr; - return false; + return surface_context_vk_->SetWindowSurface( + (native_window_ && native_window_->IsValid()) ? native_window_->handle() + : nullptr); } std::shared_ptr diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 906f4a5ee0561..c8b94fb72d37b 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -6,7 +6,7 @@ #include "flutter/impeller/core/formats.h" #include "flutter/impeller/core/texture_descriptor.h" #include "flutter/impeller/display_list/dl_image_impeller.h" -#include "flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h" +#include "flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" #include "flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h" #include "flutter/impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "flutter/impeller/renderer/backend/vulkan/texture_vk.h" @@ -54,9 +54,8 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, return; } - auto texture_source = - std::make_shared( - impeller_context_, latest_hardware_buffer, hb_desc); + auto texture_source = std::make_shared( + impeller_context_, latest_hardware_buffer, hb_desc); auto texture = std::make_shared(impeller_context_, texture_source); diff --git a/shell/platform/android/image_external_texture_vk.h b/shell/platform/android/image_external_texture_vk.h index e3d240145aacc..e702671fe84b3 100644 --- a/shell/platform/android/image_external_texture_vk.h +++ b/shell/platform/android/image_external_texture_vk.h @@ -9,7 +9,7 @@ #include #include "flutter/shell/platform/android/image_external_texture.h" -#include "flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h" +#include "flutter/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" #include "flutter/impeller/renderer/backend/vulkan/context_vk.h" #include "flutter/impeller/renderer/backend/vulkan/vk.h" #include "flutter/shell/platform/android/android_context_vulkan_impeller.h"