From 960ccb85e86cd20e92caccb0ab697be160a1b1ea Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Apr 2023 16:56:11 -0700 Subject: [PATCH 1/9] Refactor AndroidContext/Surface, particularly for Impeller. --- ci/licenses_golden/licenses_flutter | 4 + shell/platform/android/BUILD.gn | 2 + .../android/android_context_gl_impeller.cc | 218 +++++++++++++++++- .../android/android_context_gl_impeller.h | 19 ++ .../android/android_context_gl_unittests.cc | 53 +---- .../android_context_vulkan_impeller.cc | 58 +++++ .../android/android_context_vulkan_impeller.h | 35 +++ .../android/android_surface_gl_impeller.cc | 198 ++-------------- .../android/android_surface_gl_impeller.h | 17 +- .../android/android_surface_gl_skia.cc | 35 ++- .../android/android_surface_gl_skia.h | 12 +- .../android/android_surface_software.cc | 5 +- .../android/android_surface_software.h | 4 +- .../android_surface_vulkan_impeller.cc | 50 +--- .../android/android_surface_vulkan_impeller.h | 12 +- shell/platform/android/context/BUILD.gn | 1 + .../android/context/android_context.cc | 9 + .../android/context/android_context.h | 15 ++ .../external_view_embedder_unittests.cc | 35 ++- .../surface_pool_unittests.cc | 40 ++-- .../platform/android/platform_view_android.cc | 51 ++-- .../platform/android/platform_view_android.h | 6 +- .../android/surface/android_surface.cc | 6 +- .../android/surface/android_surface.h | 4 +- .../android/surface/android_surface_mock.cc | 4 - .../android/surface/android_surface_mock.h | 3 - 26 files changed, 476 insertions(+), 420 deletions(-) create mode 100644 shell/platform/android/android_context_vulkan_impeller.cc create mode 100644 shell/platform/android/android_context_vulkan_impeller.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index acd4c566d10d8..1e4cea53b1789 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2198,6 +2198,8 @@ ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_impeller.cc + ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_impeller.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_skia.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_skia.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_display.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_display.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_egl_surface.cc + ../../../flutter/LICENSE @@ -4786,6 +4788,8 @@ FILE: ../../../flutter/shell/platform/android/android_context_gl_impeller.cc FILE: ../../../flutter/shell/platform/android/android_context_gl_impeller.h FILE: ../../../flutter/shell/platform/android/android_context_gl_skia.cc FILE: ../../../flutter/shell/platform/android/android_context_gl_skia.h +FILE: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.cc +FILE: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.h FILE: ../../../flutter/shell/platform/android/android_display.cc FILE: ../../../flutter/shell/platform/android/android_display.h FILE: ../../../flutter/shell/platform/android/android_egl_surface.cc diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index e056731dd64f6..d88e20598ac9f 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -70,6 +70,8 @@ source_set("flutter_shell_native_src") { "android_context_gl_impeller.h", "android_context_gl_skia.cc", "android_context_gl_skia.h", + "android_context_vulkan_impeller.cc", + "android_context_vulkan_impeller.h", "android_display.cc", "android_display.h", "android_egl_surface.cc", diff --git a/shell/platform/android/android_context_gl_impeller.cc b/shell/platform/android/android_context_gl_impeller.cc index ff4f59a576f98..f2526596b9dbb 100644 --- a/shell/platform/android/android_context_gl_impeller.cc +++ b/shell/platform/android/android_context_gl_impeller.cc @@ -4,15 +4,229 @@ #include "flutter/shell/platform/android/android_context_gl_impeller.h" +#include "android_context_gl_impeller.h" +#include "flutter/impeller/renderer/backend/gles/context_gles.h" +#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h" +#include "flutter/impeller/renderer/backend/gles/reactor_gles.h" +#include "flutter/impeller/toolkit/egl/context.h" +#include "flutter/impeller/toolkit/egl/surface.h" +#include "impeller/entity/gles/entity_shaders_gles.h" +#include "impeller/scene/shaders/gles/scene_shaders_gles.h" + namespace flutter { +class AndroidContextGLImpeller::ReactorWorker final + : public impeller::ReactorGLES::Worker { + public: + ReactorWorker() = default; + + // |impeller::ReactorGLES::Worker| + ~ReactorWorker() override = default; + + // |impeller::ReactorGLES::Worker| + bool CanReactorReactOnCurrentThreadNow( + const impeller::ReactorGLES& reactor) const override { + impeller::ReaderLock lock(mutex_); + auto found = reactions_allowed_.find(std::this_thread::get_id()); + if (found == reactions_allowed_.end()) { + return false; + } + return found->second; + } + + void SetReactionsAllowedOnCurrentThread(bool allowed) { + impeller::WriterLock lock(mutex_); + reactions_allowed_[std::this_thread::get_id()] = allowed; + } + + private: + mutable impeller::RWMutex mutex_; + std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); +}; + +static std::shared_ptr CreateImpellerContext( + const std::shared_ptr& worker) { + auto proc_table = std::make_unique( + impeller::egl::CreateProcAddressResolver()); + + if (!proc_table->IsValid()) { + FML_LOG(ERROR) << "Could not create OpenGL proc table."; + return nullptr; + } + + std::vector> shader_mappings = { + std::make_shared( + impeller_entity_shaders_gles_data, + impeller_entity_shaders_gles_length), + std::make_shared( + impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length), + }; + + auto context = + impeller::ContextGLES::Create(std::move(proc_table), shader_mappings); + if (!context) { + FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; + return nullptr; + } + + if (!context->AddReactorWorker(worker).has_value()) { + FML_LOG(ERROR) << "Could not add reactor worker."; + return nullptr; + } + FML_LOG(ERROR) << "Using the Impeller rendering backend."; + return context; +} + AndroidContextGLImpeller::AndroidContextGLImpeller() - : AndroidContext(AndroidRenderingAPI::kOpenGLES) {} + : AndroidContext(AndroidRenderingAPI::kOpenGLES), + reactor_worker_(std::shared_ptr(new ReactorWorker())) { + auto display = std::make_unique(); + if (!display->IsValid()) { + FML_DLOG(ERROR) << "Could not create EGL display."; + return; + } + + impeller::egl::ConfigDescriptor desc; + desc.api = impeller::egl::API::kOpenGLES2; + desc.color_format = impeller::egl::ColorFormat::kRGBA8888; + desc.depth_bits = impeller::egl::DepthBits::kZero; + desc.stencil_bits = impeller::egl::StencilBits::kEight; + desc.samples = impeller::egl::Samples::kFour; + + desc.surface_type = impeller::egl::SurfaceType::kWindow; + std::unique_ptr onscreen_config = + display->ChooseConfig(desc); + if (!onscreen_config) { + // Fallback for Android emulator. + desc.samples = impeller::egl::Samples::kOne; + onscreen_config = display->ChooseConfig(desc); + if (onscreen_config) { + FML_LOG(INFO) << "Warning: This device doesn't support MSAA for onscreen " + "framebuffers. Falling back to a single sample."; + } else { + FML_DLOG(ERROR) << "Could not choose onscreen config."; + return; + } + } + + desc.surface_type = impeller::egl::SurfaceType::kPBuffer; + auto offscreen_config = display->ChooseConfig(desc); + if (!offscreen_config) { + FML_DLOG(ERROR) << "Could not choose offscreen config."; + return; + } + + auto onscreen_context = display->CreateContext(*onscreen_config, nullptr); + if (!onscreen_context) { + FML_DLOG(ERROR) << "Could not create onscreen context."; + return; + } + + auto offscreen_context = + display->CreateContext(*offscreen_config, onscreen_context.get()); + if (!offscreen_context) { + FML_DLOG(ERROR) << "Could not create offscreen context."; + return; + } + + // Creating the impeller::Context requires a current context, which requires + // some surface. + auto offscreen_surface = + display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); + if (!offscreen_context->MakeCurrent(*offscreen_surface)) { + FML_DLOG(ERROR) << "Could not make offscreen context current."; + return; + } + + auto impeller_context = CreateImpellerContext(reactor_worker_); + + if (!impeller_context) { + FML_DLOG(ERROR) << "Could not create Impeller context."; + return; + } + + if (!offscreen_context->ClearCurrent()) { + FML_DLOG(ERROR) << "Could not clear offscreen context."; + return; + } + // Setup context listeners. + impeller::egl::Context::LifecycleListener listener = + [worker = + reactor_worker_](impeller::egl ::Context::LifecycleEvent event) { + switch (event) { + case impeller::egl::Context::LifecycleEvent::kDidMakeCurrent: + worker->SetReactionsAllowedOnCurrentThread(true); + break; + case impeller::egl::Context::LifecycleEvent::kWillClearCurrent: + worker->SetReactionsAllowedOnCurrentThread(false); + break; + } + }; + if (!onscreen_context->AddLifecycleListener(listener).has_value() || + !offscreen_context->AddLifecycleListener(listener).has_value()) { + FML_DLOG(ERROR) << "Could not add lifecycle listeners"; + } + + display_ = std::move(display); + onscreen_config_ = std::move(onscreen_config); + offscreen_config_ = std::move(offscreen_config); + onscreen_context_ = std::move(onscreen_context); + offscreen_context_ = std::move(offscreen_context); + SetImpellerContext(impeller_context); + + is_valid_ = true; +} AndroidContextGLImpeller::~AndroidContextGLImpeller() = default; bool AndroidContextGLImpeller::IsValid() const { - return true; + return is_valid_; +} + +bool AndroidContextGLImpeller::ResourceContextClearCurrent() { + if (!offscreen_context_) { + return false; + } + + return offscreen_context_->ClearCurrent(); +} + +bool AndroidContextGLImpeller::ResourceContextMakeCurrent( + impeller::egl::Surface* offscreen_surface) { + if (!offscreen_context_ || !offscreen_surface) { + return false; + } + + return offscreen_context_->MakeCurrent(*offscreen_surface); +} + +std::unique_ptr +AndroidContextGLImpeller::CreateOffscreenSurface() { + return display_->CreatePixelBufferSurface(*offscreen_config_, 1u, 1u); +} + +bool AndroidContextGLImpeller::OnscreenContextMakeCurrent( + impeller::egl::Surface* onscreen_surface) { + if (!onscreen_surface || !onscreen_context_) { + return false; + } + + return onscreen_context_->MakeCurrent(*onscreen_surface); +} + +bool AndroidContextGLImpeller::OnscreenContextClearCurrent() { + if (!onscreen_context_) { + return false; + } + + return onscreen_context_->ClearCurrent(); +} + +std::unique_ptr +AndroidContextGLImpeller::CreateOnscreenSurface(EGLNativeWindowType window) { + return display_->CreateWindowSurface(*onscreen_config_, window); } } // namespace flutter diff --git a/shell/platform/android/android_context_gl_impeller.h b/shell/platform/android/android_context_gl_impeller.h index 51e9f7b128489..294ce8036afb6 100644 --- a/shell/platform/android/android_context_gl_impeller.h +++ b/shell/platform/android/android_context_gl_impeller.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_IMPELLER_H_ #include "flutter/fml/macros.h" +#include "flutter/impeller/toolkit/egl/display.h" #include "flutter/shell/platform/android/context/android_context.h" namespace flutter { @@ -19,7 +20,25 @@ class AndroidContextGLImpeller : public AndroidContext { // |AndroidContext| bool IsValid() const override; + bool ResourceContextMakeCurrent(impeller::egl::Surface* offscreen_surface); + bool ResourceContextClearCurrent(); + std::unique_ptr CreateOffscreenSurface(); + bool OnscreenContextMakeCurrent(impeller::egl::Surface* onscreen_surface); + bool OnscreenContextClearCurrent(); + std::unique_ptr CreateOnscreenSurface( + EGLNativeWindowType window); + private: + class ReactorWorker; + + std::shared_ptr reactor_worker_; + std::unique_ptr display_; + std::unique_ptr onscreen_config_; + std::unique_ptr offscreen_config_; + std::unique_ptr onscreen_context_; + std::unique_ptr offscreen_context_; + bool is_valid_ = false; + FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGLImpeller); }; diff --git a/shell/platform/android/android_context_gl_unittests.cc b/shell/platform/android/android_context_gl_unittests.cc index bf1c7a78407ec..500ec7e74c313 100644 --- a/shell/platform/android/android_context_gl_unittests.cc +++ b/shell/platform/android/android_context_gl_unittests.cc @@ -6,7 +6,6 @@ #include "flutter/shell/platform/android/android_egl_surface.h" #include "flutter/shell/platform/android/android_environment_gl.h" #include "flutter/shell/platform/android/android_surface_gl_skia.h" -#include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -14,52 +13,6 @@ namespace flutter { namespace testing { namespace android { namespace { -class MockPlatformViewAndroidJNI : public PlatformViewAndroidJNI { - public: - MOCK_METHOD2(FlutterViewHandlePlatformMessage, - void(std::unique_ptr message, - int responseId)); - MOCK_METHOD2(FlutterViewHandlePlatformMessageResponse, - void(int responseId, std::unique_ptr data)); - MOCK_METHOD3(FlutterViewUpdateSemantics, - void(std::vector buffer, - std::vector strings, - std::vector> string_attribute_args)); - MOCK_METHOD2(FlutterViewUpdateCustomAccessibilityActions, - void(std::vector actions_buffer, - std::vector strings)); - MOCK_METHOD0(FlutterViewOnFirstFrame, void()); - MOCK_METHOD0(FlutterViewOnPreEngineRestart, void()); - MOCK_METHOD2(SurfaceTextureAttachToGLContext, - void(JavaLocalRef surface_texture, int textureId)); - MOCK_METHOD1(SurfaceTextureUpdateTexImage, - void(JavaLocalRef surface_texture)); - MOCK_METHOD2(SurfaceTextureGetTransformMatrix, - void(JavaLocalRef surface_texture, SkMatrix& transform)); - MOCK_METHOD1(SurfaceTextureDetachFromGLContext, - void(JavaLocalRef surface_texture)); - MOCK_METHOD8(FlutterViewOnDisplayPlatformView, - void(int view_id, - int x, - int y, - int width, - int height, - int viewWidth, - int viewHeight, - MutatorsStack mutators_stack)); - MOCK_METHOD5(FlutterViewDisplayOverlaySurface, - void(int surface_id, int x, int y, int width, int height)); - MOCK_METHOD0(FlutterViewBeginFrame, void()); - MOCK_METHOD0(FlutterViewEndFrame, void()); - MOCK_METHOD0(FlutterViewCreateOverlaySurface, - std::unique_ptr()); - MOCK_METHOD0(FlutterViewDestroyOverlaySurfaces, void()); - MOCK_METHOD1(FlutterViewComputePlatformResolvedLocale, - std::unique_ptr>( - std::vector supported_locales_data)); - MOCK_METHOD0(GetDisplayRefreshRate, double()); - MOCK_METHOD1(RequestDartDeferredLibrary, bool(int loading_unit_id)); -}; TaskRunners MakeTaskRunners(const std::string& thread_label, const ThreadHost& thread_host) { @@ -128,9 +81,8 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNotNull) { TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto android_context = std::make_shared( AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0); - auto jni = std::make_shared(); auto android_surface = - std::make_unique(android_context, jni); + std::make_unique(android_context); auto window = fml::MakeRefCounted( nullptr, /*is_fake_window=*/true); android_surface->SetNativeWindow(window); @@ -156,9 +108,8 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) { TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto android_context = std::make_shared( AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0); - auto jni = std::make_shared(); auto android_surface = - std::make_unique(android_context, jni); + std::make_unique(android_context); EXPECT_EQ(android_surface->GetOnscreenSurface(), nullptr); android_surface->CreateSnapshotSurface(); EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr); diff --git a/shell/platform/android/android_context_vulkan_impeller.cc b/shell/platform/android/android_context_vulkan_impeller.cc new file mode 100644 index 0000000000000..8f523d4a2c356 --- /dev/null +++ b/shell/platform/android/android_context_vulkan_impeller.cc @@ -0,0 +1,58 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/android/android_context_vulkan_impeller.h" + +#include "flutter/fml/paths.h" +#include "flutter/impeller/entity/vk/entity_shaders_vk.h" +#include "flutter/impeller/entity/vk/modern_shaders_vk.h" +#include "flutter/impeller/renderer/backend/vulkan/context_vk.h" +#include "flutter/impeller/scene/shaders/vk/scene_shaders_vk.h" + +namespace flutter { + +static std::shared_ptr CreateImpellerContext( + const fml::RefPtr& proc_table, + const std::shared_ptr& concurrent_loop, + bool enable_vulkan_validation) { + std::vector> shader_mappings = { + std::make_shared(impeller_entity_shaders_vk_data, + impeller_entity_shaders_vk_length), + std::make_shared(impeller_scene_shaders_vk_data, + impeller_scene_shaders_vk_length), + std::make_shared(impeller_modern_shaders_vk_data, + impeller_modern_shaders_vk_length), + }; + + PFN_vkGetInstanceProcAddr instance_proc_addr = + proc_table->NativeGetInstanceProcAddr(); + + impeller::ContextVK::Settings settings; + settings.proc_address_callback = instance_proc_addr; + settings.shader_libraries_data = std::move(shader_mappings); + settings.cache_directory = fml::paths::GetCachesDirectory(); + settings.worker_task_runner = concurrent_loop->GetTaskRunner(); + settings.enable_validation = enable_vulkan_validation; + return impeller::ContextVK::Create(std::move(settings)); +} + +AndroidContextVulkanImpeller::AndroidContextVulkanImpeller( + bool enable_validation) + : AndroidContext(AndroidRenderingAPI::kVulkan), + proc_table_(fml::MakeRefCounted()), + workers_(fml::ConcurrentMessageLoop::Create()) { + auto impeller_context = + CreateImpellerContext(proc_table_, workers_, enable_validation); + SetImpellerContext(impeller_context); + is_valid_ = + proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context; +} + +AndroidContextVulkanImpeller::~AndroidContextVulkanImpeller() = default; + +bool AndroidContextVulkanImpeller::IsValid() const { + return is_valid_; +} + +} // namespace flutter diff --git a/shell/platform/android/android_context_vulkan_impeller.h b/shell/platform/android/android_context_vulkan_impeller.h new file mode 100644 index 0000000000000..3fe5c627e593b --- /dev/null +++ b/shell/platform/android/android_context_vulkan_impeller.h @@ -0,0 +1,35 @@ +// 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_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_ +#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_ + +#include "flutter/fml/concurrent_message_loop.h" +#include "flutter/fml/macros.h" +#include "flutter/impeller/toolkit/egl/display.h" +#include "flutter/shell/platform/android/context/android_context.h" +#include "flutter/vulkan/procs/vulkan_proc_table.h" + +namespace flutter { + +class AndroidContextVulkanImpeller : public AndroidContext { + public: + explicit AndroidContextVulkanImpeller(bool enable_validation); + + ~AndroidContextVulkanImpeller(); + + // |AndroidContext| + bool IsValid() const override; + + private: + fml::RefPtr proc_table_; + std::shared_ptr workers_; + bool is_valid_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextVulkanImpeller); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_ diff --git a/shell/platform/android/android_surface_gl_impeller.cc b/shell/platform/android/android_surface_gl_impeller.cc index ca4040ec5e6fc..f9b763e4d5f89 100644 --- a/shell/platform/android/android_surface_gl_impeller.cc +++ b/shell/platform/android/android_surface_gl_impeller.cc @@ -5,184 +5,31 @@ #include "flutter/shell/platform/android/android_surface_gl_impeller.h" #include "flutter/fml/logging.h" -#include "flutter/impeller/renderer/backend/gles/context_gles.h" -#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h" -#include "flutter/impeller/toolkit/egl/context.h" #include "flutter/impeller/toolkit/egl/surface.h" #include "flutter/shell/gpu/gpu_surface_gl_impeller.h" -#include "impeller/entity/gles/entity_shaders_gles.h" -#include "impeller/scene/shaders/gles/scene_shaders_gles.h" namespace flutter { -class AndroidSurfaceGLImpeller::ReactorWorker final - : public impeller::ReactorGLES::Worker { - public: - ReactorWorker() = default; - - // |impeller::ReactorGLES::Worker| - ~ReactorWorker() override = default; - - // |impeller::ReactorGLES::Worker| - bool CanReactorReactOnCurrentThreadNow( - const impeller::ReactorGLES& reactor) const override { - impeller::ReaderLock lock(mutex_); - auto found = reactions_allowed_.find(std::this_thread::get_id()); - if (found == reactions_allowed_.end()) { - return false; - } - return found->second; - } - - void SetReactionsAllowedOnCurrentThread(bool allowed) { - impeller::WriterLock lock(mutex_); - reactions_allowed_[std::this_thread::get_id()] = allowed; - } - - private: - mutable impeller::RWMutex mutex_; - std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); - - FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); -}; - -static std::shared_ptr CreateImpellerContext( - const std::shared_ptr& worker) { - auto proc_table = std::make_unique( - impeller::egl::CreateProcAddressResolver()); - - if (!proc_table->IsValid()) { - FML_LOG(ERROR) << "Could not create OpenGL proc table."; - return nullptr; - } - - std::vector> shader_mappings = { - std::make_shared( - impeller_entity_shaders_gles_data, - impeller_entity_shaders_gles_length), - std::make_shared( - impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length), - }; - - auto context = - impeller::ContextGLES::Create(std::move(proc_table), shader_mappings); - if (!context) { - FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; - return nullptr; - } - - if (!context->AddReactorWorker(worker).has_value()) { - FML_LOG(ERROR) << "Could not add reactor worker."; - return nullptr; - } - FML_LOG(ERROR) << "Using the Impeller rendering backend."; - return context; -} - AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade) - : AndroidSurface(android_context), - reactor_worker_(std::shared_ptr(new ReactorWorker())) { - auto display = std::make_unique(); - if (!display->IsValid()) { - FML_DLOG(ERROR) << "Could not create EGL display."; - return; - } - - impeller::egl::ConfigDescriptor desc; - desc.api = impeller::egl::API::kOpenGLES2; - desc.color_format = impeller::egl::ColorFormat::kRGBA8888; - desc.depth_bits = impeller::egl::DepthBits::kZero; - desc.stencil_bits = impeller::egl::StencilBits::kEight; - desc.samples = impeller::egl::Samples::kFour; + const std::shared_ptr& android_context) + : android_context_(android_context) { + offscreen_surface_ = android_context_->CreateOffscreenSurface(); - desc.surface_type = impeller::egl::SurfaceType::kWindow; - std::unique_ptr onscreen_config = - display->ChooseConfig(desc); - if (!onscreen_config) { - // Fallback for Android emulator. - desc.samples = impeller::egl::Samples::kOne; - onscreen_config = display->ChooseConfig(desc); - if (onscreen_config) { - FML_LOG(INFO) << "Warning: This device doesn't support MSAA for onscreen " - "framebuffers. Falling back to a single sample."; - } else { - FML_DLOG(ERROR) << "Could not choose onscreen config."; - return; - } - } - - desc.surface_type = impeller::egl::SurfaceType::kPBuffer; - auto offscreen_config = display->ChooseConfig(desc); - if (!offscreen_config) { - FML_DLOG(ERROR) << "Could not choose offscreen config."; - return; - } - - auto onscreen_context = display->CreateContext(*onscreen_config, nullptr); - if (!onscreen_context) { - FML_DLOG(ERROR) << "Could not create onscreen context."; - return; - } - - auto offscreen_context = - display->CreateContext(*offscreen_config, onscreen_context.get()); - if (!offscreen_context) { - FML_DLOG(ERROR) << "Could not create offscreen context."; - return; - } - - auto offscreen_surface = - display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); - if (!offscreen_surface) { + if (!offscreen_surface_) { FML_DLOG(ERROR) << "Could not create offscreen surface."; return; } - if (!offscreen_context->MakeCurrent(*offscreen_surface)) { + if (!android_context_->ResourceContextMakeCurrent(offscreen_surface_.get())) { FML_DLOG(ERROR) << "Could not make offscreen context current."; return; } - auto impeller_context = CreateImpellerContext(reactor_worker_); - - if (!impeller_context) { - FML_DLOG(ERROR) << "Could not create Impeller context."; - return; - } - - if (!offscreen_context->ClearCurrent()) { + if (!android_context_->ResourceContextClearCurrent()) { FML_DLOG(ERROR) << "Could not clear offscreen context."; return; } - // Setup context listeners. - impeller::egl::Context::LifecycleListener listener = - [worker = - reactor_worker_](impeller::egl ::Context::LifecycleEvent event) { - switch (event) { - case impeller::egl::Context::LifecycleEvent::kDidMakeCurrent: - worker->SetReactionsAllowedOnCurrentThread(true); - break; - case impeller::egl::Context::LifecycleEvent::kWillClearCurrent: - worker->SetReactionsAllowedOnCurrentThread(false); - break; - } - }; - if (!onscreen_context->AddLifecycleListener(listener).has_value() || - !offscreen_context->AddLifecycleListener(listener).has_value()) { - FML_DLOG(ERROR) << "Could not add lifecycle listeners"; - } - - display_ = std::move(display); - onscreen_config_ = std::move(onscreen_config); - offscreen_config_ = std::move(offscreen_config); - offscreen_surface_ = std::move(offscreen_surface); - onscreen_context_ = std::move(onscreen_context); - offscreen_context_ = std::move(offscreen_context); - impeller_context_ = std::move(impeller_context); - // The onscreen surface will be acquired once the native window is set. is_valid_ = true; @@ -198,10 +45,10 @@ bool AndroidSurfaceGLImpeller::IsValid() const { // |AndroidSurface| std::unique_ptr AndroidSurfaceGLImpeller::CreateGPUSurface( GrDirectContext* gr_context) { - auto surface = - std::make_unique(this, // delegate - impeller_context_ // context - ); + auto surface = std::make_unique( + this, // delegate + android_context_->GetImpellerContext() // context + ); if (!surface->IsValid()) { return nullptr; } @@ -223,20 +70,15 @@ bool AndroidSurfaceGLImpeller::OnScreenSurfaceResize(const SkISize& size) { // |AndroidSurface| bool AndroidSurfaceGLImpeller::ResourceContextMakeCurrent() { - if (!offscreen_context_ || !offscreen_surface_) { + if (!offscreen_surface_) { return false; } - - return offscreen_context_->MakeCurrent(*offscreen_surface_); + return android_context_->ResourceContextMakeCurrent(offscreen_surface_.get()); } // |AndroidSurface| bool AndroidSurfaceGLImpeller::ResourceContextClearCurrent() { - if (!offscreen_context_ || !offscreen_surface_) { - return false; - } - - return offscreen_context_->ClearCurrent(); + return android_context_->ResourceContextClearCurrent(); } // |AndroidSurface| @@ -254,7 +96,7 @@ std::unique_ptr AndroidSurfaceGLImpeller::CreateSnapshotSurface() { // |AndroidSurface| std::shared_ptr AndroidSurfaceGLImpeller::GetImpellerContext() { - return impeller_context_; + return android_context_->GetImpellerContext(); } // |GPUSurfaceGLDelegate| @@ -264,20 +106,20 @@ AndroidSurfaceGLImpeller::GLContextMakeCurrent() { } bool AndroidSurfaceGLImpeller::OnGLContextMakeCurrent() { - if (!onscreen_surface_ || !onscreen_context_) { + if (!onscreen_surface_) { return false; } - return onscreen_context_->MakeCurrent(*onscreen_surface_); + return android_context_->OnscreenContextMakeCurrent(onscreen_surface_.get()); } // |GPUSurfaceGLDelegate| bool AndroidSurfaceGLImpeller::GLContextClearCurrent() { - if (!onscreen_surface_ || !onscreen_context_) { + if (!onscreen_surface_) { return false; } - return onscreen_context_->ClearCurrent(); + return android_context_->OnscreenContextClearCurrent(); } // |GPUSurfaceGLDelegate| @@ -326,8 +168,8 @@ bool AndroidSurfaceGLImpeller:: return false; } onscreen_surface_.reset(); - auto onscreen_surface = display_->CreateWindowSurface( - *onscreen_config_, native_window_->handle()); + auto onscreen_surface = + android_context_->CreateOnscreenSurface(native_window_->handle()); if (!onscreen_surface) { FML_DLOG(ERROR) << "Could not create onscreen surface."; return false; diff --git a/shell/platform/android/android_surface_gl_impeller.h b/shell/platform/android/android_surface_gl_impeller.h index b8ca423072f60..3066a8552ee25 100644 --- a/shell/platform/android/android_surface_gl_impeller.h +++ b/shell/platform/android/android_surface_gl_impeller.h @@ -7,8 +7,8 @@ #include "flutter/fml/macros.h" #include "flutter/impeller/renderer/context.h" -#include "flutter/impeller/toolkit/egl/display.h" #include "flutter/shell/gpu/gpu_surface_gl_delegate.h" +#include "flutter/shell/platform/android/android_context_gl_impeller.h" #include "flutter/shell/platform/android/surface/android_native_window.h" #include "flutter/shell/platform/android/surface/android_surface.h" @@ -17,9 +17,8 @@ namespace flutter { class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, public AndroidSurface { public: - AndroidSurfaceGLImpeller( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade); + explicit AndroidSurfaceGLImpeller( + const std::shared_ptr& android_context); // |AndroidSurface| ~AndroidSurfaceGLImpeller() override; @@ -74,17 +73,9 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, sk_sp GetGLInterface() const override; private: - class ReactorWorker; - - std::shared_ptr reactor_worker_; - std::unique_ptr display_; - std::unique_ptr onscreen_config_; - std::unique_ptr offscreen_config_; + std::shared_ptr android_context_; std::unique_ptr onscreen_surface_; std::unique_ptr offscreen_surface_; - std::unique_ptr onscreen_context_; - std::unique_ptr offscreen_context_; - std::shared_ptr impeller_context_; fml::RefPtr native_window_; bool is_valid_ = false; diff --git a/shell/platform/android/android_surface_gl_skia.cc b/shell/platform/android/android_surface_gl_skia.cc index 343d691e2ae75..d6ec0c3cf3d96 100644 --- a/shell/platform/android/android_surface_gl_skia.cc +++ b/shell/platform/android/android_surface_gl_skia.cc @@ -21,14 +21,13 @@ constexpr char kEmulatorRendererPrefix[] = } // anonymous namespace AndroidSurfaceGLSkia::AndroidSurfaceGLSkia( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade) - : AndroidSurface(android_context), + const std::shared_ptr& android_context) + : android_context_(android_context), native_window_(nullptr), onscreen_surface_(nullptr), offscreen_surface_(nullptr) { // Acquire the offscreen surface. - offscreen_surface_ = GLContextPtr()->CreateOffscreenSurface(); + offscreen_surface_ = android_context_->CreateOffscreenSurface(); if (!offscreen_surface_->IsValid()) { offscreen_surface_ = nullptr; } @@ -40,12 +39,12 @@ void AndroidSurfaceGLSkia::TeardownOnScreenContext() { // When the onscreen surface is destroyed, the context and the surface // instance should be deleted. Issue: // https://github.com/flutter/flutter/issues/64414 - GLContextPtr()->ClearCurrent(); + android_context_->ClearCurrent(); onscreen_surface_ = nullptr; } bool AndroidSurfaceGLSkia::IsValid() const { - return offscreen_surface_ && GLContextPtr()->IsValid(); + return offscreen_surface_ && android_context_->IsValid(); } std::unique_ptr AndroidSurfaceGLSkia::CreateGPUSurface( @@ -55,10 +54,10 @@ std::unique_ptr AndroidSurfaceGLSkia::CreateGPUSurface( true); } else { sk_sp main_skia_context = - GLContextPtr()->GetMainSkiaContext(); + android_context_->GetMainSkiaContext(); if (!main_skia_context) { main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this); - GLContextPtr()->SetMainSkiaContext(main_skia_context); + android_context_->SetMainSkiaContext(main_skia_context); } return std::make_unique(main_skia_context, this, true); } @@ -73,12 +72,12 @@ bool AndroidSurfaceGLSkia::OnScreenSurfaceResize(const SkISize& size) { return true; } - GLContextPtr()->ClearCurrent(); + android_context_->ClearCurrent(); // Ensure the destructor is called since it destroys the `EGLSurface` before // creating a new onscreen surface. onscreen_surface_ = nullptr; - onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_); + onscreen_surface_ = android_context_->CreateOnscreenSurface(native_window_); if (!onscreen_surface_->IsValid()) { FML_LOG(ERROR) << "Unable to create EGL window surface on resize."; return false; @@ -109,7 +108,7 @@ bool AndroidSurfaceGLSkia::SetNativeWindow( // creating a new onscreen surface. onscreen_surface_ = nullptr; // Create the onscreen surface. - onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(window); + onscreen_surface_ = android_context_->CreateOnscreenSurface(window); if (!onscreen_surface_->IsValid()) { return false; } @@ -127,7 +126,7 @@ std::unique_ptr AndroidSurfaceGLSkia::GLContextMakeCurrent() { bool AndroidSurfaceGLSkia::GLContextClearCurrent() { FML_DCHECK(IsValid()); - return GLContextPtr()->ClearCurrent(); + return android_context_->ClearCurrent(); } SurfaceFrame::FramebufferInfo AndroidSurfaceGLSkia::GLContextFramebufferInfo() @@ -186,7 +185,7 @@ sk_sp AndroidSurfaceGLSkia::GetGLInterface() const { reinterpret_cast(glGetString(GL_RENDERER)); if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix, strlen(kEmulatorRendererPrefix)) == 0) { - EGLContext new_context = GLContextPtr()->CreateNewContext(); + EGLContext new_context = android_context_->CreateNewContext(); if (new_context != EGL_NO_CONTEXT) { EGLContext old_context = eglGetCurrentContext(); EGLDisplay display = eglGetCurrentDisplay(); @@ -205,19 +204,15 @@ sk_sp AndroidSurfaceGLSkia::GetGLInterface() const { return GPUSurfaceGLDelegate::GetGLInterface(); } -AndroidContextGLSkia* AndroidSurfaceGLSkia::GLContextPtr() const { - return reinterpret_cast(android_context_.get()); -} - std::unique_ptr AndroidSurfaceGLSkia::CreateSnapshotSurface() { if (!onscreen_surface_ || !onscreen_surface_->IsValid()) { - onscreen_surface_ = GLContextPtr()->CreatePbufferSurface(); + onscreen_surface_ = android_context_->CreatePbufferSurface(); } sk_sp main_skia_context = - GLContextPtr()->GetMainSkiaContext(); + android_context_->GetMainSkiaContext(); if (!main_skia_context) { main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this); - GLContextPtr()->SetMainSkiaContext(main_skia_context); + android_context_->SetMainSkiaContext(main_skia_context); } return std::make_unique(main_skia_context, this, true); diff --git a/shell/platform/android/android_surface_gl_skia.h b/shell/platform/android/android_surface_gl_skia.h index 274c28f2c6760..1c35692dc3a0e 100644 --- a/shell/platform/android/android_surface_gl_skia.h +++ b/shell/platform/android/android_surface_gl_skia.h @@ -21,9 +21,8 @@ namespace flutter { class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate, public AndroidSurface { public: - AndroidSurfaceGLSkia( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade); + explicit AndroidSurfaceGLSkia( + const std::shared_ptr& android_context); ~AndroidSurfaceGLSkia() override; @@ -82,16 +81,11 @@ class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate, } private: + std::shared_ptr android_context_; fml::RefPtr native_window_; std::unique_ptr onscreen_surface_; std::unique_ptr offscreen_surface_; - //---------------------------------------------------------------------------- - /// @brief Takes the super class AndroidSurface's AndroidContext and - /// return a raw pointer to an AndroidContextGL. - /// - AndroidContextGLSkia* GLContextPtr() const; - FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGLSkia); }; diff --git a/shell/platform/android/android_surface_software.cc b/shell/platform/android/android_surface_software.cc index fdfc8d9d509ac..0d1a2d9e2c180 100644 --- a/shell/platform/android/android_surface_software.cc +++ b/shell/platform/android/android_surface_software.cc @@ -40,10 +40,7 @@ bool GetSkColorType(int32_t buffer_format, } // anonymous namespace -AndroidSurfaceSoftware::AndroidSurfaceSoftware( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade) - : AndroidSurface(android_context) { +AndroidSurfaceSoftware::AndroidSurfaceSoftware() { GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_, &target_alpha_type_); } diff --git a/shell/platform/android/android_surface_software.h b/shell/platform/android/android_surface_software.h index 38e4c498f3843..1b7083aa7dda1 100644 --- a/shell/platform/android/android_surface_software.h +++ b/shell/platform/android/android_surface_software.h @@ -19,9 +19,7 @@ namespace flutter { class AndroidSurfaceSoftware final : public AndroidSurface, public GPUSurfaceSoftwareDelegate { public: - AndroidSurfaceSoftware( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade); + AndroidSurfaceSoftware(); ~AndroidSurfaceSoftware() override; diff --git a/shell/platform/android/android_surface_vulkan_impeller.cc b/shell/platform/android/android_surface_vulkan_impeller.cc index 0e5ac734e3b89..e5d2416af90bb 100644 --- a/shell/platform/android/android_surface_vulkan_impeller.cc +++ b/shell/platform/android/android_surface_vulkan_impeller.cc @@ -10,52 +10,16 @@ #include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/logging.h" #include "flutter/fml/memory/ref_ptr.h" -#include "flutter/fml/paths.h" #include "flutter/impeller/renderer/backend/vulkan/context_vk.h" #include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h" #include "flutter/vulkan/vulkan_native_surface_android.h" -#include "impeller/entity/vk/entity_shaders_vk.h" -#include "impeller/entity/vk/modern_shaders_vk.h" -#include "impeller/scene/shaders/vk/scene_shaders_vk.h" namespace flutter { -static std::shared_ptr CreateImpellerContext( - const fml::RefPtr& proc_table, - const std::shared_ptr& concurrent_loop, - bool enable_vulkan_validation) { - std::vector> shader_mappings = { - std::make_shared(impeller_entity_shaders_vk_data, - impeller_entity_shaders_vk_length), - std::make_shared(impeller_scene_shaders_vk_data, - impeller_scene_shaders_vk_length), - std::make_shared(impeller_modern_shaders_vk_data, - impeller_modern_shaders_vk_length), - }; - - PFN_vkGetInstanceProcAddr instance_proc_addr = - proc_table->NativeGetInstanceProcAddr(); - - impeller::ContextVK::Settings settings; - settings.proc_address_callback = instance_proc_addr; - settings.shader_libraries_data = std::move(shader_mappings); - settings.cache_directory = fml::paths::GetCachesDirectory(); - settings.worker_task_runner = concurrent_loop->GetTaskRunner(); - settings.enable_validation = enable_vulkan_validation; - return impeller::ContextVK::Create(std::move(settings)); -} - AndroidSurfaceVulkanImpeller::AndroidSurfaceVulkanImpeller( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade, - bool enable_vulkan_validation) - : AndroidSurface(android_context), - proc_table_(fml::MakeRefCounted()), - workers_(fml::ConcurrentMessageLoop::Create()) { - impeller_context_ = - CreateImpellerContext(proc_table_, workers_, enable_vulkan_validation); - is_valid_ = - proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context_; + const std::shared_ptr& android_context) + : android_context_(android_context) { + is_valid_ = android_context_->IsValid(); } AndroidSurfaceVulkanImpeller::~AndroidSurfaceVulkanImpeller() = default; @@ -79,7 +43,8 @@ std::unique_ptr AndroidSurfaceVulkanImpeller::CreateGPUSurface( } std::unique_ptr gpu_surface = - std::make_unique(impeller_context_); + std::make_unique( + android_context_->GetImpellerContext()); if (!gpu_surface->IsValid()) { return nullptr; @@ -105,7 +70,8 @@ bool AndroidSurfaceVulkanImpeller::SetNativeWindow( native_window_ = std::move(window); bool success = native_window_ && native_window_->IsValid(); if (success) { - auto& context_vk = impeller::ContextVK::Cast(*impeller_context_); + auto& context_vk = + impeller::ContextVK::Cast(*android_context_->GetImpellerContext()); auto surface = context_vk.CreateAndroidSurface(native_window_->handle()); if (!surface) { @@ -122,7 +88,7 @@ bool AndroidSurfaceVulkanImpeller::SetNativeWindow( std::shared_ptr AndroidSurfaceVulkanImpeller::GetImpellerContext() { - return impeller_context_; + return android_context_->GetImpellerContext(); } } // namespace flutter diff --git a/shell/platform/android/android_surface_vulkan_impeller.h b/shell/platform/android/android_surface_vulkan_impeller.h index 3fff43d9d974c..548a0a5a4cf69 100644 --- a/shell/platform/android/android_surface_vulkan_impeller.h +++ b/shell/platform/android/android_surface_vulkan_impeller.h @@ -7,18 +7,16 @@ #include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/macros.h" #include "flutter/impeller/renderer/context.h" +#include "flutter/shell/platform/android/android_context_vulkan_impeller.h" #include "flutter/shell/platform/android/surface/android_native_window.h" #include "flutter/shell/platform/android/surface/android_surface.h" -#include "flutter/vulkan/procs/vulkan_proc_table.h" namespace flutter { class AndroidSurfaceVulkanImpeller : public AndroidSurface { public: - AndroidSurfaceVulkanImpeller( - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade, - bool enable_vulkan_validation); + explicit AndroidSurfaceVulkanImpeller( + const std::shared_ptr& android_context); ~AndroidSurfaceVulkanImpeller() override; @@ -48,10 +46,8 @@ class AndroidSurfaceVulkanImpeller : public AndroidSurface { bool SetNativeWindow(fml::RefPtr window) override; private: - fml::RefPtr proc_table_; + std::shared_ptr android_context_; fml::RefPtr native_window_; - std::shared_ptr workers_; - std::shared_ptr impeller_context_; bool is_valid_ = false; FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceVulkanImpeller); diff --git a/shell/platform/android/context/BUILD.gn b/shell/platform/android/context/BUILD.gn index 89918491187d3..a75549cab04d5 100644 --- a/shell/platform/android/context/BUILD.gn +++ b/shell/platform/android/context/BUILD.gn @@ -15,6 +15,7 @@ source_set("context") { deps = [ "//flutter/fml", + "//flutter/impeller/renderer", "//third_party/skia", ] diff --git a/shell/platform/android/context/android_context.cc b/shell/platform/android/context/android_context.cc index 1d4badf9543b7..3d7c4e619d97b 100644 --- a/shell/platform/android/context/android_context.cc +++ b/shell/platform/android/context/android_context.cc @@ -32,4 +32,13 @@ sk_sp AndroidContext::GetMainSkiaContext() const { return main_context_; } +std::shared_ptr AndroidContext::GetImpellerContext() const { + return impeller_context_; +} + +void AndroidContext::SetImpellerContext( + const std::shared_ptr& context) { + impeller_context_ = context; +} + } // namespace flutter diff --git a/shell/platform/android/context/android_context.h b/shell/platform/android/context/android_context.h index 0bed23e398674..ac3b7d49dee8a 100644 --- a/shell/platform/android/context/android_context.h +++ b/shell/platform/android/context/android_context.h @@ -7,6 +7,7 @@ #include "flutter/fml/macros.h" #include "flutter/fml/task_runner.h" +#include "flutter/impeller/renderer/context.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { @@ -14,6 +15,7 @@ namespace flutter { enum class AndroidRenderingAPI { kSoftware, kOpenGLES, + kVulkan, }; //------------------------------------------------------------------------------ @@ -54,12 +56,25 @@ class AndroidContext { /// sk_sp GetMainSkiaContext() const; + //---------------------------------------------------------------------------- + /// @brief Accessor for the Impeller context associated with + /// AndroidSurfaces and the raster thread. + /// + std::shared_ptr GetImpellerContext() const; + + protected: + /// Intended to be called from a subclass constructor after setup work for the + /// context has completed. + void SetImpellerContext(const std::shared_ptr& context); + private: const AndroidRenderingAPI rendering_api_; // This is the Skia context used for on-screen rendering. sk_sp main_context_; + std::shared_ptr impeller_context_; + FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext); }; diff --git a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc index b9c527b16c710..c2d90ae2b10de 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc @@ -264,7 +264,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size, framebuffer_info]() { + [gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -284,8 +284,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { .WillOnce(Return(ByMove(std::move(surface_frame_1)))) .WillOnce(Return(ByMove(std::move(surface_frame_2)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -472,7 +471,7 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size, framebuffer_info]() { + [gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -485,8 +484,7 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) { .Times(1 /* frames */) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -571,7 +569,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size, framebuffer_info]() { + [gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -584,8 +582,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) { .Times(1 /* frames */) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -675,7 +672,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size, framebuffer_info]() { + [gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -688,8 +685,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) { .Times(1 /* frames */) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -764,7 +760,7 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size, framebuffer_info]() { + [gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -776,8 +772,7 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -853,7 +848,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size, framebuffer_info]() { + [gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -865,8 +860,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -978,7 +972,7 @@ TEST(AndroidExternalViewEmbedder, Teardown) { auto gr_context = GrDirectContext::MakeMock(nullptr); auto frame_size = SkISize::Make(1000, 1000); auto surface_factory = std::make_shared( - [&android_context, gr_context, window, frame_size]() { + [gr_context, window, frame_size]() { SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, @@ -991,8 +985,7 @@ TEST(AndroidExternalViewEmbedder, Teardown) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = - std::make_unique(android_context); + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) .WillOnce(Return(ByMove(std::move(surface_mock)))); diff --git a/shell/platform/android/external_view_embedder/surface_pool_unittests.cc b/shell/platform/android/external_view_embedder/surface_pool_unittests.cc index ecf4e1a6c78e9..d0c505675fe09 100644 --- a/shell/platform/android/external_view_embedder/surface_pool_unittests.cc +++ b/shell/platform/android/external_view_embedder/surface_pool_unittests.cc @@ -50,10 +50,9 @@ TEST(SurfacePool, GetLayerAllocateOneLayer) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = std::make_shared( - [&android_context, gr_context, window]() { - auto android_surface_mock = - std::make_unique(android_context); + auto surface_factory = + std::make_shared([gr_context, window]() { + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -82,10 +81,9 @@ TEST(SurfacePool, GetUnusedLayers) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = std::make_shared( - [&android_context, gr_context, window]() { - auto android_surface_mock = - std::make_unique(android_context); + auto surface_factory = + std::make_shared([gr_context, window]() { + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -118,9 +116,8 @@ TEST(SurfacePool, GetLayerRecycle) { auto gr_context_2 = GrDirectContext::MakeMock(nullptr); auto surface_factory = std::make_shared( - [&android_context, gr_context_1, gr_context_2, window]() { - auto android_surface_mock = - std::make_unique(android_context); + [gr_context_1, gr_context_2, window]() { + auto android_surface_mock = std::make_unique(); // Allocate two GPU surfaces for each gr context. EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context_1.get())); @@ -166,10 +163,9 @@ TEST(SurfacePool, GetLayerAllocateTwoLayers) { ByMove(std::make_unique( 1, window)))); - auto surface_factory = std::make_shared( - [&android_context, gr_context, window]() { - auto android_surface_mock = - std::make_unique(android_context); + auto surface_factory = + std::make_shared([gr_context, window]() { + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -206,10 +202,9 @@ TEST(SurfacePool, DestroyLayers) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = std::make_shared( - [&android_context, gr_context, window]() { - auto android_surface_mock = - std::make_unique(android_context); + auto surface_factory = + std::make_shared([gr_context, window]() { + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -236,10 +231,9 @@ TEST(SurfacePool, DestroyLayersFrameSizeChanged) { auto window = fml::MakeRefCounted(nullptr); - auto surface_factory = std::make_shared( - [&android_context, gr_context, window]() { - auto android_surface_mock = - std::make_unique(android_context); + auto surface_factory = + std::make_shared([gr_context, window]() { + auto android_surface_mock = std::make_unique(); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 804b0f111de7b..1ee2c8926b302 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -31,36 +31,29 @@ namespace flutter { AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl( const std::shared_ptr& context, - std::shared_ptr jni_facade, - bool enable_impeller, - bool enable_vulkan_validation) - : android_context_(context), - jni_facade_(std::move(jni_facade)), - enable_impeller_(enable_impeller), - enable_vulkan_validation_(enable_vulkan_validation) {} + bool enable_impeller) + : android_context_(context), enable_impeller_(enable_impeller) {} AndroidSurfaceFactoryImpl::~AndroidSurfaceFactoryImpl() = default; std::unique_ptr AndroidSurfaceFactoryImpl::CreateSurface() { switch (android_context_->RenderingApi()) { case AndroidRenderingAPI::kSoftware: - return std::make_unique(android_context_, - jni_facade_); + return std::make_unique(); case AndroidRenderingAPI::kOpenGLES: if (enable_impeller_) { -// TODO(kaushikiska@): Enable this after wiring a preference for Vulkan backend. -#if false - return std::make_unique( - android_context_, jni_facade_, enable_vulkan_validation_); - -#else - return std::make_unique(android_context_, - jni_facade_); -#endif + return std::make_unique( + std::static_pointer_cast( + android_context_)); } else { - return std::make_unique(android_context_, - jni_facade_); + return std::make_unique( + std::static_pointer_cast(android_context_)); } + case AndroidRenderingAPI::kVulkan: + FML_DCHECK(enable_impeller_); + return std::make_unique( + std::static_pointer_cast( + android_context_)); default: FML_DCHECK(false); return nullptr; @@ -71,12 +64,19 @@ static std::shared_ptr CreateAndroidContext( bool use_software_rendering, const flutter::TaskRunners& task_runners, uint8_t msaa_samples, - bool enable_impeller) { + bool enable_impeller, + bool enable_vulkan_validation) { if (use_software_rendering) { return std::make_shared(AndroidRenderingAPI::kSoftware); } if (enable_impeller) { + // TODO(kaushikiska@): Enable this after wiring a preference for Vulkan + // backend. +#if false + return std::make_unique(enable_vulkan_validation); +#else return std::make_unique(); +#endif } return std::make_unique( AndroidRenderingAPI::kOpenGLES, // @@ -100,7 +100,8 @@ PlatformViewAndroid::PlatformViewAndroid( use_software_rendering, task_runners, msaa_samples, - delegate.OnPlatformViewGetSettings().enable_impeller)) {} + delegate.OnPlatformViewGetSettings().enable_impeller, + delegate.OnPlatformViewGetSettings().enable_vulkan_validation)) {} PlatformViewAndroid::PlatformViewAndroid( PlatformView::Delegate& delegate, @@ -116,10 +117,8 @@ PlatformViewAndroid::PlatformViewAndroid( FML_CHECK(android_context_->IsValid()) << "Could not create surface from invalid Android context."; surface_factory_ = std::make_shared( - android_context_, // - jni_facade_, // - delegate.OnPlatformViewGetSettings().enable_impeller, // - delegate.OnPlatformViewGetSettings().enable_vulkan_validation // + android_context_, // + delegate.OnPlatformViewGetSettings().enable_impeller // ); android_surface_ = surface_factory_->CreateSurface(); FML_CHECK(android_surface_ && android_surface_->IsValid()) diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index d7a8e8ce65751..069b2f920b3af 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -27,9 +27,7 @@ namespace flutter { class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory { public: AndroidSurfaceFactoryImpl(const std::shared_ptr& context, - std::shared_ptr jni_facade, - bool enable_impeller, - bool enable_vulkan_validation); + bool enable_impeller); ~AndroidSurfaceFactoryImpl() override; @@ -37,9 +35,7 @@ class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory { private: const std::shared_ptr& android_context_; - std::shared_ptr jni_facade_; const bool enable_impeller_; - const bool enable_vulkan_validation_; }; class PlatformViewAndroid final : public PlatformView { diff --git a/shell/platform/android/surface/android_surface.cc b/shell/platform/android/surface/android_surface.cc index ab96387edbd77..e301491b5fce0 100644 --- a/shell/platform/android/surface/android_surface.cc +++ b/shell/platform/android/surface/android_surface.cc @@ -7,11 +7,7 @@ namespace flutter { -AndroidSurface::AndroidSurface( - const std::shared_ptr& android_context) { - FML_DCHECK(android_context->IsValid()); - android_context_ = android_context; -} +AndroidSurface::AndroidSurface() = default; AndroidSurface::~AndroidSurface() = default; diff --git a/shell/platform/android/surface/android_surface.h b/shell/platform/android/surface/android_surface.h index 485f619e1a81b..7eae6c68e7d71 100644 --- a/shell/platform/android/surface/android_surface.h +++ b/shell/platform/android/surface/android_surface.h @@ -46,9 +46,7 @@ class AndroidSurface { virtual std::shared_ptr GetImpellerContext(); protected: - explicit AndroidSurface( - const std::shared_ptr& android_context); - std::shared_ptr android_context_; + AndroidSurface(); }; class AndroidSurfaceFactory { diff --git a/shell/platform/android/surface/android_surface_mock.cc b/shell/platform/android/surface/android_surface_mock.cc index 8f718fcae667a..0f7c6d1a6d80c 100644 --- a/shell/platform/android/surface/android_surface_mock.cc +++ b/shell/platform/android/surface/android_surface_mock.cc @@ -6,10 +6,6 @@ namespace flutter { -AndroidSurfaceMock::AndroidSurfaceMock( - const std::shared_ptr& android_context) - : AndroidSurface(android_context) {} - std::unique_ptr AndroidSurfaceMock::GLContextMakeCurrent() { return std::make_unique(/*static_result=*/true); } diff --git a/shell/platform/android/surface/android_surface_mock.h b/shell/platform/android/surface/android_surface_mock.h index 3f326a21920b7..411816698cb74 100644 --- a/shell/platform/android/surface/android_surface_mock.h +++ b/shell/platform/android/surface/android_surface_mock.h @@ -18,9 +18,6 @@ namespace flutter { class AndroidSurfaceMock final : public GPUSurfaceGLDelegate, public AndroidSurface { public: - explicit AndroidSurfaceMock( - const std::shared_ptr& android_context); - MOCK_METHOD(bool, IsValid, (), (const, override)); MOCK_METHOD(void, TeardownOnScreenContext, (), (override)); From 77b891600751cdd71f5a6344cc0a57e15a34cc5d Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Apr 2023 10:13:24 -0700 Subject: [PATCH 2/9] Fix toImage/toImageSync. Makes the impeller::Context available to the rasterizer ASAP, so that even if it has not received a surface yet calls to `toImage` and `toImageSync` can still produce a texture. --- flow/surface.cc | 2 +- flow/surface.h | 2 +- shell/common/rasterizer.cc | 6 ++- shell/common/rasterizer.h | 16 +++++++ shell/common/shell.cc | 23 +++++----- shell/common/shell_unittests.cc | 47 ++++++++++++++++++++ shell/common/snapshot_controller.h | 5 +++ shell/common/snapshot_controller_impeller.cc | 7 +-- shell/gpu/gpu_surface_gl_impeller.cc | 5 ++- shell/gpu/gpu_surface_gl_impeller.h | 2 +- shell/gpu/gpu_surface_metal_impeller.h | 2 +- shell/gpu/gpu_surface_metal_impeller.mm | 4 +- shell/gpu/gpu_surface_vulkan_impeller.cc | 5 ++- shell/gpu/gpu_surface_vulkan_impeller.h | 2 +- 14 files changed, 101 insertions(+), 27 deletions(-) diff --git a/flow/surface.cc b/flow/surface.cc index fbd3d427c2de2..795d74780d8fc 100644 --- a/flow/surface.cc +++ b/flow/surface.cc @@ -26,7 +26,7 @@ bool Surface::EnableRasterCache() const { return true; } -impeller::AiksContext* Surface::GetAiksContext() const { +std::shared_ptr Surface::GetAiksContext() const { return nullptr; } diff --git a/flow/surface.h b/flow/surface.h index 5cc5d6def08a1..f824e0eb9bd8e 100644 --- a/flow/surface.h +++ b/flow/surface.h @@ -49,7 +49,7 @@ class Surface { virtual bool EnableRasterCache() const; - virtual impeller::AiksContext* GetAiksContext() const; + virtual std::shared_ptr GetAiksContext() const; /// Capture the `SurfaceData` currently present in the surface. /// diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index c2ae9dd1bed8b..c9d2e0ddb6876 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -52,6 +52,10 @@ fml::TaskRunnerAffineWeakPtr Rasterizer::GetSnapshotDelegate() const { return weak_factory_.GetWeakPtr(); } +void Rasterizer::SetImpellerContext( + std::weak_ptr impeller_context) { + impeller_context_ = std::move(impeller_context); +} void Rasterizer::Setup(std::unique_ptr surface) { surface_ = std::move(surface); @@ -544,7 +548,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( .supports_readback, // surface supports pixel reads raster_thread_merger_, // thread merger frame->GetDisplayListBuilder().get(), // display list builder - surface_->GetAiksContext() // aiks context + surface_->GetAiksContext().get() // aiks context ); if (compositor_frame) { compositor_context_->raster_cache().BeginFrame(); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index a122820c427ab..6e8875e3aa924 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -23,6 +23,8 @@ #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/fml/time/time_delta.h" #include "flutter/fml/time/time_point.h" +#include "flutter/impeller/aiks/aiks_context.h" +#include "flutter/impeller/renderer/context.h" #include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/shell/common/pipeline.h" #include "flutter/shell/common/snapshot_controller.h" @@ -140,6 +142,8 @@ class Rasterizer final : public SnapshotDelegate, /// ~Rasterizer(); + void SetImpellerContext(std::weak_ptr impeller_context); + //---------------------------------------------------------------------------- /// @brief Rasterizers may be created well before an on-screen surface is /// available for rendering. Shells usually create a rasterizer in @@ -509,6 +513,17 @@ class Rasterizer final : public SnapshotDelegate, return surface_; } + // |SnapshotController::Delegate| + std::shared_ptr GetAiksContext() const override { + if (surface_) { + return surface_->GetAiksContext(); + } + if (auto context = impeller_context_.lock()) { + return std::make_shared(context); + } + return nullptr; + } + // |SnapshotController::Delegate| const std::unique_ptr& GetSnapshotSurfaceProducer() const override { @@ -544,6 +559,7 @@ class Rasterizer final : public SnapshotDelegate, Delegate& delegate_; MakeGpuImageBehavior gpu_image_behavior_; + std::weak_ptr impeller_context_; std::unique_ptr surface_; std::unique_ptr snapshot_surface_producer_; std::unique_ptr compositor_context_; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 32a777d3583ba..59ff44d6047c9 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -186,6 +186,12 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( !settings.skia_deterministic_rendering_on_cpu), is_gpu_disabled)); + // Create the platform view on the platform thread (this thread). + auto platform_view = on_create_platform_view(*shell.get()); + if (!platform_view || !platform_view->GetWeakPtr()) { + return nullptr; + } + // Create the rasterizer on the raster thread. std::promise> rasterizer_promise; auto rasterizer_future = rasterizer_promise.get_future(); @@ -193,23 +199,20 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( snapshot_delegate_promise; auto snapshot_delegate_future = snapshot_delegate_promise.get_future(); fml::TaskRunner::RunNowOrPostTask( - task_runners.GetRasterTaskRunner(), [&rasterizer_promise, // - &snapshot_delegate_promise, - on_create_rasterizer, // - shell = shell.get() // + task_runners.GetRasterTaskRunner(), + [&rasterizer_promise, // + &snapshot_delegate_promise, + on_create_rasterizer, // + shell = shell.get(), // + impeller_context = platform_view->GetImpellerContext() // ]() { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); std::unique_ptr rasterizer(on_create_rasterizer(*shell)); + rasterizer->SetImpellerContext(std::move(impeller_context)); snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate()); rasterizer_promise.set_value(std::move(rasterizer)); }); - // Create the platform view on the platform thread (this thread). - auto platform_view = on_create_platform_view(*shell.get()); - if (!platform_view || !platform_view->GetWeakPtr()) { - return nullptr; - } - // Ask the platform view for the vsync waiter. This will be used by the engine // to create the animator. auto vsync_waiter = platform_view->CreateVSyncWaiter(); diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index aac516ad37f38..b443ac61569f2 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -3986,6 +3986,53 @@ TEST_F(ShellTest, PictureToImageSync) { DestroyShell(std::move(shell)); } +TEST_F(ShellTest, PictureToImageSyncImpellerNoSurface) { +#if !SHELL_ENABLE_GL + // This test uses the GL backend. + GTEST_SKIP(); +#endif // !SHELL_ENABLE_GL + auto settings = CreateSettingsForFixture(); + settings.enable_impeller = true; + std::unique_ptr shell = + CreateShell(settings, // + GetTaskRunnersForFixture(), // + false, // + nullptr, // + false, // + ShellTestPlatformView::BackendType::kGLBackend // + ); + + AddNativeCallback("NativeOnBeforeToImageSync", + CREATE_NATIVE_ENTRY([&](auto args) { + // nop + })); + + fml::CountDownLatch latch(2); + AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&](auto args) { + // Teardown and set up rasterizer again. + PlatformViewNotifyDestroyed(shell.get()); + PlatformViewNotifyCreated(shell.get()); + latch.CountDown(); + })); + + ASSERT_NE(shell, nullptr); + ASSERT_TRUE(shell->IsSetup()); + auto configuration = RunConfiguration::InferFromSettings(settings); + + // Important: Do not create the platform view yet! + // This test is making sure that the rasterizer can create the texture + // as expected without a surface. + + configuration.SetEntrypoint("toImageSync"); + RunEngine(shell.get(), std::move(configuration)); + PumpOneFrame(shell.get()); + + latch.Wait(); + + PlatformViewNotifyDestroyed(shell.get()); + DestroyShell(std::move(shell)); +} + #if SHELL_ENABLE_GL // This test uses the GL backend and refers to symbols in egl.h TEST_F(ShellTest, PictureToImageSyncWithTrampledContext) { diff --git a/shell/common/snapshot_controller.h b/shell/common/snapshot_controller.h index 11651325edd43..54ad5e0b061c7 100644 --- a/shell/common/snapshot_controller.h +++ b/shell/common/snapshot_controller.h @@ -12,6 +12,10 @@ #include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/shell/common/snapshot_surface_producer.h" +namespace impeller { +class AiksContext; +} + namespace flutter { class SnapshotController { @@ -20,6 +24,7 @@ class SnapshotController { public: virtual ~Delegate() = default; virtual const std::unique_ptr& GetSurface() const = 0; + virtual std::shared_ptr GetAiksContext() const = 0; virtual const std::unique_ptr& GetSnapshotSurfaceProducer() const = 0; virtual std::shared_ptr GetIsGpuDisabledSyncSwitch() diff --git a/shell/common/snapshot_controller_impeller.cc b/shell/common/snapshot_controller_impeller.cc index 5e7317805812d..c9bafd9c0e27a 100644 --- a/shell/common/snapshot_controller_impeller.cc +++ b/shell/common/snapshot_controller_impeller.cc @@ -36,11 +36,8 @@ sk_sp SnapshotControllerImpeller::DoMakeRasterSnapshot( impeller::DisplayListDispatcher dispatcher; display_list->Dispatch(dispatcher); impeller::Picture picture = dispatcher.EndRecordingAsPicture(); - if (GetDelegate().GetSurface() && - GetDelegate().GetSurface()->GetAiksContext()) { - impeller::AiksContext* context = - GetDelegate().GetSurface()->GetAiksContext(); - + auto context = GetDelegate().GetAiksContext(); + if (context) { auto max_size = context->GetContext() ->GetResourceAllocator() ->GetMaxTextureSizeSupported(); diff --git a/shell/gpu/gpu_surface_gl_impeller.cc b/shell/gpu/gpu_surface_gl_impeller.cc index 2a7386613c781..d65a9b5bd2666 100644 --- a/shell/gpu/gpu_surface_gl_impeller.cc +++ b/shell/gpu/gpu_surface_gl_impeller.cc @@ -160,8 +160,9 @@ bool GPUSurfaceGLImpeller::EnableRasterCache() const { } // |Surface| -impeller::AiksContext* GPUSurfaceGLImpeller::GetAiksContext() const { - return aiks_context_.get(); +std::shared_ptr GPUSurfaceGLImpeller::GetAiksContext() + const { + return aiks_context_; } } // namespace flutter diff --git a/shell/gpu/gpu_surface_gl_impeller.h b/shell/gpu/gpu_surface_gl_impeller.h index 367bad23835ac..048c8570e1140 100644 --- a/shell/gpu/gpu_surface_gl_impeller.h +++ b/shell/gpu/gpu_surface_gl_impeller.h @@ -56,7 +56,7 @@ class GPUSurfaceGLImpeller final : public Surface { bool EnableRasterCache() const override; // |Surface| - impeller::AiksContext* GetAiksContext() const override; + std::shared_ptr GetAiksContext() const override; FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGLImpeller); }; diff --git a/shell/gpu/gpu_surface_metal_impeller.h b/shell/gpu/gpu_surface_metal_impeller.h index 6254d851a5062..71a11013218b7 100644 --- a/shell/gpu/gpu_surface_metal_impeller.h +++ b/shell/gpu/gpu_surface_metal_impeller.h @@ -54,7 +54,7 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalImpeller : public Surface { bool EnableRasterCache() const override; // |Surface| - impeller::AiksContext* GetAiksContext() const override; + std::shared_ptr GetAiksContext() const override; FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceMetalImpeller); }; diff --git a/shell/gpu/gpu_surface_metal_impeller.mm b/shell/gpu/gpu_surface_metal_impeller.mm index bad9f26ca780d..0362c7c86b1d1 100644 --- a/shell/gpu/gpu_surface_metal_impeller.mm +++ b/shell/gpu/gpu_surface_metal_impeller.mm @@ -129,8 +129,8 @@ } // |Surface| -impeller::AiksContext* GPUSurfaceMetalImpeller::GetAiksContext() const { - return aiks_context_.get(); +std::shared_ptr GPUSurfaceMetalImpeller::GetAiksContext() const { + return aiks_context_; } Surface::SurfaceData GPUSurfaceMetalImpeller::GetSurfaceData() const { diff --git a/shell/gpu/gpu_surface_vulkan_impeller.cc b/shell/gpu/gpu_surface_vulkan_impeller.cc index 0e3854900a54f..1e8d437f7b5c6 100644 --- a/shell/gpu/gpu_surface_vulkan_impeller.cc +++ b/shell/gpu/gpu_surface_vulkan_impeller.cc @@ -122,8 +122,9 @@ bool GPUSurfaceVulkanImpeller::EnableRasterCache() const { } // |Surface| -impeller::AiksContext* GPUSurfaceVulkanImpeller::GetAiksContext() const { - return aiks_context_.get(); +std::shared_ptr +GPUSurfaceVulkanImpeller::GetAiksContext() const { + return aiks_context_; } } // namespace flutter diff --git a/shell/gpu/gpu_surface_vulkan_impeller.h b/shell/gpu/gpu_surface_vulkan_impeller.h index cf72b2e0e18c9..7eca3ecd17f43 100644 --- a/shell/gpu/gpu_surface_vulkan_impeller.h +++ b/shell/gpu/gpu_surface_vulkan_impeller.h @@ -47,7 +47,7 @@ class GPUSurfaceVulkanImpeller final : public Surface { bool EnableRasterCache() const override; // |Surface| - impeller::AiksContext* GetAiksContext() const override; + std::shared_ptr GetAiksContext() const override; FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkanImpeller); }; From 3fa00aefa6251da45d44ae57d1d125eb9ca0d368 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Apr 2023 15:01:48 -0700 Subject: [PATCH 3/9] Use Metal instead --- shell/common/shell.cc | 2 +- shell/common/shell_test_platform_view_metal.h | 3 ++ .../common/shell_test_platform_view_metal.mm | 31 ++++++++++++++++--- shell/common/shell_unittests.cc | 18 +++++------ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 59ff44d6047c9..214b3b384569c 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -208,7 +208,7 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( ]() { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); std::unique_ptr rasterizer(on_create_rasterizer(*shell)); - rasterizer->SetImpellerContext(std::move(impeller_context)); + rasterizer->SetImpellerContext(impeller_context); snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate()); rasterizer_promise.set_value(std::move(rasterizer)); }); diff --git a/shell/common/shell_test_platform_view_metal.h b/shell/common/shell_test_platform_view_metal.h index be9dc9ebd4de2..8dd015cd2408d 100644 --- a/shell/common/shell_test_platform_view_metal.h +++ b/shell/common/shell_test_platform_view_metal.h @@ -49,6 +49,9 @@ class ShellTestPlatformViewMetal final : public ShellTestPlatformView, // |PlatformView| std::unique_ptr CreateRenderingSurface() override; + // |PlatformView| + std::shared_ptr GetImpellerContext() const override; + // |GPUSurfaceMetalDelegate| GPUCAMetalLayerHandle GetCAMetalLayer( const SkISize& frame_info) const override; diff --git a/shell/common/shell_test_platform_view_metal.mm b/shell/common/shell_test_platform_view_metal.mm index 814e67e6f3933..4b5bee88639fa 100644 --- a/shell/common/shell_test_platform_view_metal.mm +++ b/shell/common/shell_test_platform_view_metal.mm @@ -9,7 +9,9 @@ #include #include "flutter/fml/platform/darwin/scoped_nsobject.h" +#include "flutter/shell/gpu/gpu_surface_metal_impeller.h" #include "flutter/shell/gpu/gpu_surface_metal_skia.h" +#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h" #include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" namespace flutter { @@ -29,12 +31,17 @@ // non-Objective-C TUs. class DarwinContextMetal { public: - DarwinContextMetal() - : context_([[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]), - offscreen_texture_(CreateOffscreenTexture([context_.get() device])) {} + DarwinContextMetal(bool impeller) + : context_(impeller ? nil : [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]), + impeller_context_(impeller ? [[FlutterDarwinContextMetalImpeller alloc] init] : nil), + offscreen_texture_(CreateOffscreenTexture(MTLCreateSystemDefaultDevice())) {} ~DarwinContextMetal() = default; + fml::scoped_nsobject impeller_context() const { + return impeller_context_; + } + fml::scoped_nsobject context() const { return context_; } fml::scoped_nsprotocol> offscreen_texture() const { return offscreen_texture_; } @@ -48,6 +55,7 @@ GPUMTLTextureInfo offscreen_texture_info() const { private: const fml::scoped_nsobject context_; + const fml::scoped_nsobject impeller_context_; const fml::scoped_nsprotocol> offscreen_texture_; FML_DISALLOW_COPY_AND_ASSIGN(DarwinContextMetal); @@ -61,11 +69,15 @@ GPUMTLTextureInfo offscreen_texture_info() const { std::shared_ptr shell_test_external_view_embedder) : ShellTestPlatformView(delegate, task_runners), GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture), - metal_context_(std::make_unique()), + metal_context_(std::make_unique(GetSettings().enable_impeller)), create_vsync_waiter_(std::move(create_vsync_waiter)), vsync_clock_(std::move(vsync_clock)), shell_test_external_view_embedder_(std::move(shell_test_external_view_embedder)) { - FML_CHECK([metal_context_->context() mainContext] != nil); + if (GetSettings().enable_impeller) { + FML_CHECK([metal_context_->impeller_context() context] != nil); + } else { + FML_CHECK([metal_context_->context() mainContext] != nil); + } } ShellTestPlatformViewMetal::~ShellTestPlatformViewMetal() = default; @@ -93,10 +105,19 @@ GPUMTLTextureInfo offscreen_texture_info() const { // |PlatformView| std::unique_ptr ShellTestPlatformViewMetal::CreateRenderingSurface() { + if (GetSettings().enable_impeller) { + return std::make_unique(this, + [metal_context_->impeller_context() context]); + } return std::make_unique(this, [metal_context_->context() mainContext], MsaaSampleCount::kNone); } +// |PlatformView| +std::shared_ptr ShellTestPlatformViewMetal::GetImpellerContext() const { + return [metal_context_->impeller_context() context]; +} + // |GPUSurfaceMetalDelegate| GPUCAMetalLayerHandle ShellTestPlatformViewMetal::GetCAMetalLayer(const SkISize& frame_info) const { FML_CHECK(false) << "A Metal Delegate configured with MTLRenderTargetType::kMTLTexture was asked " diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index b443ac61569f2..82dc5b3682457 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -3987,19 +3987,19 @@ TEST_F(ShellTest, PictureToImageSync) { } TEST_F(ShellTest, PictureToImageSyncImpellerNoSurface) { -#if !SHELL_ENABLE_GL - // This test uses the GL backend. +#if !SHELL_ENABLE_METAL + // This test uses the Metal backend. GTEST_SKIP(); -#endif // !SHELL_ENABLE_GL +#endif // !SHELL_ENABLE_METAL auto settings = CreateSettingsForFixture(); settings.enable_impeller = true; std::unique_ptr shell = - CreateShell(settings, // - GetTaskRunnersForFixture(), // - false, // - nullptr, // - false, // - ShellTestPlatformView::BackendType::kGLBackend // + CreateShell(settings, // + GetTaskRunnersForFixture(), // + false, // + nullptr, // + false, // + ShellTestPlatformView::BackendType::kMetalBackend // ); AddNativeCallback("NativeOnBeforeToImageSync", From a682562bd51b6d51c612087143c3c7d6978c30f7 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Apr 2023 15:19:24 -0700 Subject: [PATCH 4/9] fix Fuchsia builds --- shell/common/rasterizer.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 6e8875e3aa924..e8a0ca7963b44 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -23,8 +23,10 @@ #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/fml/time/time_delta.h" #include "flutter/fml/time/time_point.h" +#if IMPELLER_SUPPORTS_RENDERING #include "flutter/impeller/aiks/aiks_context.h" #include "flutter/impeller/renderer/context.h" +#endif // IMPELLER_SUPPORTS_RENDERING #include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/shell/common/pipeline.h" #include "flutter/shell/common/snapshot_controller.h" @@ -35,6 +37,13 @@ #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/gpu/GrDirectContext.h" +#if !IMPELLER_SUPPORTS_RENDERING +namespace impeller { +class Context; +class AiksContext; +} // namespace impeller +#endif // !IMPELLER_SUPPORTS_RENDERING + namespace flutter { //------------------------------------------------------------------------------ @@ -515,12 +524,14 @@ class Rasterizer final : public SnapshotDelegate, // |SnapshotController::Delegate| std::shared_ptr GetAiksContext() const override { +#if IMPELLER_SUPPORTS_RENDERING if (surface_) { return surface_->GetAiksContext(); } if (auto context = impeller_context_.lock()) { return std::make_shared(context); } +#endif return nullptr; } From d570bbb2bb2b6dd5cf7a5145577e5911817ce0be Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Apr 2023 16:05:14 -0700 Subject: [PATCH 5/9] Fix multi-engine impeller --- shell/platform/android/android_surface_gl_impeller.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/shell/platform/android/android_surface_gl_impeller.cc b/shell/platform/android/android_surface_gl_impeller.cc index f9b763e4d5f89..662541ab64b55 100644 --- a/shell/platform/android/android_surface_gl_impeller.cc +++ b/shell/platform/android/android_surface_gl_impeller.cc @@ -20,16 +20,6 @@ AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( return; } - if (!android_context_->ResourceContextMakeCurrent(offscreen_surface_.get())) { - FML_DLOG(ERROR) << "Could not make offscreen context current."; - return; - } - - if (!android_context_->ResourceContextClearCurrent()) { - FML_DLOG(ERROR) << "Could not clear offscreen context."; - return; - } - // The onscreen surface will be acquired once the native window is set. is_valid_ = true; From d8a8ec2e8d04b835b91afd5a4f7446a2dd430fd6 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Apr 2023 17:39:18 -0700 Subject: [PATCH 6/9] Fix lint issue, nogncheck --- shell/common/rasterizer.h | 7 ++++--- shell/common/shell_test_platform_view_metal.mm | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index e8a0ca7963b44..23227f5d67618 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -24,9 +24,10 @@ #include "flutter/fml/time/time_delta.h" #include "flutter/fml/time/time_point.h" #if IMPELLER_SUPPORTS_RENDERING -#include "flutter/impeller/aiks/aiks_context.h" -#include "flutter/impeller/renderer/context.h" -#endif // IMPELLER_SUPPORTS_RENDERING +// GN is having trouble understanding how this works in the Fuchsia builds. +#include "flutter/impeller/aiks/aiks_context.h" // nogncheck +#include "flutter/impeller/renderer/context.h" // nogncheck +#endif // IMPELLER_SUPPORTS_RENDERING #include "flutter/lib/ui/snapshot_delegate.h" #include "flutter/shell/common/pipeline.h" #include "flutter/shell/common/snapshot_controller.h" diff --git a/shell/common/shell_test_platform_view_metal.mm b/shell/common/shell_test_platform_view_metal.mm index 4b5bee88639fa..c00df9896ef36 100644 --- a/shell/common/shell_test_platform_view_metal.mm +++ b/shell/common/shell_test_platform_view_metal.mm @@ -34,7 +34,8 @@ DarwinContextMetal(bool impeller) : context_(impeller ? nil : [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]), impeller_context_(impeller ? [[FlutterDarwinContextMetalImpeller alloc] init] : nil), - offscreen_texture_(CreateOffscreenTexture(MTLCreateSystemDefaultDevice())) {} + offscreen_texture_(CreateOffscreenTexture( + impeller ? [impeller_context_ context]->GetMTLDevice() : [context_ device])) {} ~DarwinContextMetal() = default; From 7b61b22a6f1b51e38f935dd2f80daf44fd5907b9 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Apr 2023 18:51:53 -0700 Subject: [PATCH 7/9] explicit --- shell/common/shell_test_platform_view_metal.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/common/shell_test_platform_view_metal.mm b/shell/common/shell_test_platform_view_metal.mm index c00df9896ef36..701bba7737a22 100644 --- a/shell/common/shell_test_platform_view_metal.mm +++ b/shell/common/shell_test_platform_view_metal.mm @@ -31,7 +31,7 @@ // non-Objective-C TUs. class DarwinContextMetal { public: - DarwinContextMetal(bool impeller) + explicit DarwinContextMetal(bool impeller) : context_(impeller ? nil : [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]), impeller_context_(impeller ? [[FlutterDarwinContextMetalImpeller alloc] init] : nil), offscreen_texture_(CreateOffscreenTexture( From e427f1f979edad11b3f0c5e30e3ad45f7d3f7d35 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 13 Apr 2023 13:35:04 -0700 Subject: [PATCH 8/9] revert android changes --- ci/licenses_golden/licenses_flutter | 4 - shell/platform/android/BUILD.gn | 2 - .../android/android_context_gl_impeller.cc | 218 +----------------- .../android/android_context_gl_impeller.h | 19 -- .../android/android_context_gl_unittests.cc | 53 ++++- .../android_context_vulkan_impeller.cc | 58 ----- .../android/android_context_vulkan_impeller.h | 35 --- .../android/android_surface_gl_impeller.cc | 204 ++++++++++++++-- .../android/android_surface_gl_impeller.h | 17 +- .../android/android_surface_gl_skia.cc | 35 +-- .../android/android_surface_gl_skia.h | 12 +- .../android/android_surface_software.cc | 5 +- .../android/android_surface_software.h | 4 +- .../android_surface_vulkan_impeller.cc | 50 +++- .../android/android_surface_vulkan_impeller.h | 12 +- shell/platform/android/context/BUILD.gn | 1 - .../android/context/android_context.cc | 9 - .../android/context/android_context.h | 15 -- .../external_view_embedder_unittests.cc | 35 +-- .../surface_pool_unittests.cc | 40 ++-- .../platform/android/platform_view_android.cc | 51 ++-- .../platform/android/platform_view_android.h | 6 +- .../android/surface/android_surface.cc | 6 +- .../android/surface/android_surface.h | 4 +- .../android/surface/android_surface_mock.cc | 4 + .../android/surface/android_surface_mock.h | 3 + 26 files changed, 428 insertions(+), 474 deletions(-) delete mode 100644 shell/platform/android/android_context_vulkan_impeller.cc delete mode 100644 shell/platform/android/android_context_vulkan_impeller.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ada1f80cf4399..66fdc6c94173b 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2196,8 +2196,6 @@ ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_impeller.cc + ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_impeller.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_skia.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_context_gl_skia.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_display.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_display.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_egl_surface.cc + ../../../flutter/LICENSE @@ -4785,8 +4783,6 @@ FILE: ../../../flutter/shell/platform/android/android_context_gl_impeller.cc FILE: ../../../flutter/shell/platform/android/android_context_gl_impeller.h FILE: ../../../flutter/shell/platform/android/android_context_gl_skia.cc FILE: ../../../flutter/shell/platform/android/android_context_gl_skia.h -FILE: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.cc -FILE: ../../../flutter/shell/platform/android/android_context_vulkan_impeller.h FILE: ../../../flutter/shell/platform/android/android_display.cc FILE: ../../../flutter/shell/platform/android/android_display.h FILE: ../../../flutter/shell/platform/android/android_egl_surface.cc diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index d88e20598ac9f..e056731dd64f6 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -70,8 +70,6 @@ source_set("flutter_shell_native_src") { "android_context_gl_impeller.h", "android_context_gl_skia.cc", "android_context_gl_skia.h", - "android_context_vulkan_impeller.cc", - "android_context_vulkan_impeller.h", "android_display.cc", "android_display.h", "android_egl_surface.cc", diff --git a/shell/platform/android/android_context_gl_impeller.cc b/shell/platform/android/android_context_gl_impeller.cc index f2526596b9dbb..ff4f59a576f98 100644 --- a/shell/platform/android/android_context_gl_impeller.cc +++ b/shell/platform/android/android_context_gl_impeller.cc @@ -4,229 +4,15 @@ #include "flutter/shell/platform/android/android_context_gl_impeller.h" -#include "android_context_gl_impeller.h" -#include "flutter/impeller/renderer/backend/gles/context_gles.h" -#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h" -#include "flutter/impeller/renderer/backend/gles/reactor_gles.h" -#include "flutter/impeller/toolkit/egl/context.h" -#include "flutter/impeller/toolkit/egl/surface.h" -#include "impeller/entity/gles/entity_shaders_gles.h" -#include "impeller/scene/shaders/gles/scene_shaders_gles.h" - namespace flutter { -class AndroidContextGLImpeller::ReactorWorker final - : public impeller::ReactorGLES::Worker { - public: - ReactorWorker() = default; - - // |impeller::ReactorGLES::Worker| - ~ReactorWorker() override = default; - - // |impeller::ReactorGLES::Worker| - bool CanReactorReactOnCurrentThreadNow( - const impeller::ReactorGLES& reactor) const override { - impeller::ReaderLock lock(mutex_); - auto found = reactions_allowed_.find(std::this_thread::get_id()); - if (found == reactions_allowed_.end()) { - return false; - } - return found->second; - } - - void SetReactionsAllowedOnCurrentThread(bool allowed) { - impeller::WriterLock lock(mutex_); - reactions_allowed_[std::this_thread::get_id()] = allowed; - } - - private: - mutable impeller::RWMutex mutex_; - std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); - - FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); -}; - -static std::shared_ptr CreateImpellerContext( - const std::shared_ptr& worker) { - auto proc_table = std::make_unique( - impeller::egl::CreateProcAddressResolver()); - - if (!proc_table->IsValid()) { - FML_LOG(ERROR) << "Could not create OpenGL proc table."; - return nullptr; - } - - std::vector> shader_mappings = { - std::make_shared( - impeller_entity_shaders_gles_data, - impeller_entity_shaders_gles_length), - std::make_shared( - impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length), - }; - - auto context = - impeller::ContextGLES::Create(std::move(proc_table), shader_mappings); - if (!context) { - FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; - return nullptr; - } - - if (!context->AddReactorWorker(worker).has_value()) { - FML_LOG(ERROR) << "Could not add reactor worker."; - return nullptr; - } - FML_LOG(ERROR) << "Using the Impeller rendering backend."; - return context; -} - AndroidContextGLImpeller::AndroidContextGLImpeller() - : AndroidContext(AndroidRenderingAPI::kOpenGLES), - reactor_worker_(std::shared_ptr(new ReactorWorker())) { - auto display = std::make_unique(); - if (!display->IsValid()) { - FML_DLOG(ERROR) << "Could not create EGL display."; - return; - } - - impeller::egl::ConfigDescriptor desc; - desc.api = impeller::egl::API::kOpenGLES2; - desc.color_format = impeller::egl::ColorFormat::kRGBA8888; - desc.depth_bits = impeller::egl::DepthBits::kZero; - desc.stencil_bits = impeller::egl::StencilBits::kEight; - desc.samples = impeller::egl::Samples::kFour; - - desc.surface_type = impeller::egl::SurfaceType::kWindow; - std::unique_ptr onscreen_config = - display->ChooseConfig(desc); - if (!onscreen_config) { - // Fallback for Android emulator. - desc.samples = impeller::egl::Samples::kOne; - onscreen_config = display->ChooseConfig(desc); - if (onscreen_config) { - FML_LOG(INFO) << "Warning: This device doesn't support MSAA for onscreen " - "framebuffers. Falling back to a single sample."; - } else { - FML_DLOG(ERROR) << "Could not choose onscreen config."; - return; - } - } - - desc.surface_type = impeller::egl::SurfaceType::kPBuffer; - auto offscreen_config = display->ChooseConfig(desc); - if (!offscreen_config) { - FML_DLOG(ERROR) << "Could not choose offscreen config."; - return; - } - - auto onscreen_context = display->CreateContext(*onscreen_config, nullptr); - if (!onscreen_context) { - FML_DLOG(ERROR) << "Could not create onscreen context."; - return; - } - - auto offscreen_context = - display->CreateContext(*offscreen_config, onscreen_context.get()); - if (!offscreen_context) { - FML_DLOG(ERROR) << "Could not create offscreen context."; - return; - } - - // Creating the impeller::Context requires a current context, which requires - // some surface. - auto offscreen_surface = - display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); - if (!offscreen_context->MakeCurrent(*offscreen_surface)) { - FML_DLOG(ERROR) << "Could not make offscreen context current."; - return; - } - - auto impeller_context = CreateImpellerContext(reactor_worker_); - - if (!impeller_context) { - FML_DLOG(ERROR) << "Could not create Impeller context."; - return; - } - - if (!offscreen_context->ClearCurrent()) { - FML_DLOG(ERROR) << "Could not clear offscreen context."; - return; - } - // Setup context listeners. - impeller::egl::Context::LifecycleListener listener = - [worker = - reactor_worker_](impeller::egl ::Context::LifecycleEvent event) { - switch (event) { - case impeller::egl::Context::LifecycleEvent::kDidMakeCurrent: - worker->SetReactionsAllowedOnCurrentThread(true); - break; - case impeller::egl::Context::LifecycleEvent::kWillClearCurrent: - worker->SetReactionsAllowedOnCurrentThread(false); - break; - } - }; - if (!onscreen_context->AddLifecycleListener(listener).has_value() || - !offscreen_context->AddLifecycleListener(listener).has_value()) { - FML_DLOG(ERROR) << "Could not add lifecycle listeners"; - } - - display_ = std::move(display); - onscreen_config_ = std::move(onscreen_config); - offscreen_config_ = std::move(offscreen_config); - onscreen_context_ = std::move(onscreen_context); - offscreen_context_ = std::move(offscreen_context); - SetImpellerContext(impeller_context); - - is_valid_ = true; -} + : AndroidContext(AndroidRenderingAPI::kOpenGLES) {} AndroidContextGLImpeller::~AndroidContextGLImpeller() = default; bool AndroidContextGLImpeller::IsValid() const { - return is_valid_; -} - -bool AndroidContextGLImpeller::ResourceContextClearCurrent() { - if (!offscreen_context_) { - return false; - } - - return offscreen_context_->ClearCurrent(); -} - -bool AndroidContextGLImpeller::ResourceContextMakeCurrent( - impeller::egl::Surface* offscreen_surface) { - if (!offscreen_context_ || !offscreen_surface) { - return false; - } - - return offscreen_context_->MakeCurrent(*offscreen_surface); -} - -std::unique_ptr -AndroidContextGLImpeller::CreateOffscreenSurface() { - return display_->CreatePixelBufferSurface(*offscreen_config_, 1u, 1u); -} - -bool AndroidContextGLImpeller::OnscreenContextMakeCurrent( - impeller::egl::Surface* onscreen_surface) { - if (!onscreen_surface || !onscreen_context_) { - return false; - } - - return onscreen_context_->MakeCurrent(*onscreen_surface); -} - -bool AndroidContextGLImpeller::OnscreenContextClearCurrent() { - if (!onscreen_context_) { - return false; - } - - return onscreen_context_->ClearCurrent(); -} - -std::unique_ptr -AndroidContextGLImpeller::CreateOnscreenSurface(EGLNativeWindowType window) { - return display_->CreateWindowSurface(*onscreen_config_, window); + return true; } } // namespace flutter diff --git a/shell/platform/android/android_context_gl_impeller.h b/shell/platform/android/android_context_gl_impeller.h index 294ce8036afb6..51e9f7b128489 100644 --- a/shell/platform/android/android_context_gl_impeller.h +++ b/shell/platform/android/android_context_gl_impeller.h @@ -6,7 +6,6 @@ #define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_IMPELLER_H_ #include "flutter/fml/macros.h" -#include "flutter/impeller/toolkit/egl/display.h" #include "flutter/shell/platform/android/context/android_context.h" namespace flutter { @@ -20,25 +19,7 @@ class AndroidContextGLImpeller : public AndroidContext { // |AndroidContext| bool IsValid() const override; - bool ResourceContextMakeCurrent(impeller::egl::Surface* offscreen_surface); - bool ResourceContextClearCurrent(); - std::unique_ptr CreateOffscreenSurface(); - bool OnscreenContextMakeCurrent(impeller::egl::Surface* onscreen_surface); - bool OnscreenContextClearCurrent(); - std::unique_ptr CreateOnscreenSurface( - EGLNativeWindowType window); - private: - class ReactorWorker; - - std::shared_ptr reactor_worker_; - std::unique_ptr display_; - std::unique_ptr onscreen_config_; - std::unique_ptr offscreen_config_; - std::unique_ptr onscreen_context_; - std::unique_ptr offscreen_context_; - bool is_valid_ = false; - FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGLImpeller); }; diff --git a/shell/platform/android/android_context_gl_unittests.cc b/shell/platform/android/android_context_gl_unittests.cc index 500ec7e74c313..bf1c7a78407ec 100644 --- a/shell/platform/android/android_context_gl_unittests.cc +++ b/shell/platform/android/android_context_gl_unittests.cc @@ -6,6 +6,7 @@ #include "flutter/shell/platform/android/android_egl_surface.h" #include "flutter/shell/platform/android/android_environment_gl.h" #include "flutter/shell/platform/android/android_surface_gl_skia.h" +#include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -13,6 +14,52 @@ namespace flutter { namespace testing { namespace android { namespace { +class MockPlatformViewAndroidJNI : public PlatformViewAndroidJNI { + public: + MOCK_METHOD2(FlutterViewHandlePlatformMessage, + void(std::unique_ptr message, + int responseId)); + MOCK_METHOD2(FlutterViewHandlePlatformMessageResponse, + void(int responseId, std::unique_ptr data)); + MOCK_METHOD3(FlutterViewUpdateSemantics, + void(std::vector buffer, + std::vector strings, + std::vector> string_attribute_args)); + MOCK_METHOD2(FlutterViewUpdateCustomAccessibilityActions, + void(std::vector actions_buffer, + std::vector strings)); + MOCK_METHOD0(FlutterViewOnFirstFrame, void()); + MOCK_METHOD0(FlutterViewOnPreEngineRestart, void()); + MOCK_METHOD2(SurfaceTextureAttachToGLContext, + void(JavaLocalRef surface_texture, int textureId)); + MOCK_METHOD1(SurfaceTextureUpdateTexImage, + void(JavaLocalRef surface_texture)); + MOCK_METHOD2(SurfaceTextureGetTransformMatrix, + void(JavaLocalRef surface_texture, SkMatrix& transform)); + MOCK_METHOD1(SurfaceTextureDetachFromGLContext, + void(JavaLocalRef surface_texture)); + MOCK_METHOD8(FlutterViewOnDisplayPlatformView, + void(int view_id, + int x, + int y, + int width, + int height, + int viewWidth, + int viewHeight, + MutatorsStack mutators_stack)); + MOCK_METHOD5(FlutterViewDisplayOverlaySurface, + void(int surface_id, int x, int y, int width, int height)); + MOCK_METHOD0(FlutterViewBeginFrame, void()); + MOCK_METHOD0(FlutterViewEndFrame, void()); + MOCK_METHOD0(FlutterViewCreateOverlaySurface, + std::unique_ptr()); + MOCK_METHOD0(FlutterViewDestroyOverlaySurfaces, void()); + MOCK_METHOD1(FlutterViewComputePlatformResolvedLocale, + std::unique_ptr>( + std::vector supported_locales_data)); + MOCK_METHOD0(GetDisplayRefreshRate, double()); + MOCK_METHOD1(RequestDartDeferredLibrary, bool(int loading_unit_id)); +}; TaskRunners MakeTaskRunners(const std::string& thread_label, const ThreadHost& thread_host) { @@ -81,8 +128,9 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNotNull) { TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto android_context = std::make_shared( AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0); + auto jni = std::make_shared(); auto android_surface = - std::make_unique(android_context); + std::make_unique(android_context, jni); auto window = fml::MakeRefCounted( nullptr, /*is_fake_window=*/true); android_surface->SetNativeWindow(window); @@ -108,8 +156,9 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) { TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host); auto android_context = std::make_shared( AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0); + auto jni = std::make_shared(); auto android_surface = - std::make_unique(android_context); + std::make_unique(android_context, jni); EXPECT_EQ(android_surface->GetOnscreenSurface(), nullptr); android_surface->CreateSnapshotSurface(); EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr); diff --git a/shell/platform/android/android_context_vulkan_impeller.cc b/shell/platform/android/android_context_vulkan_impeller.cc deleted file mode 100644 index 8f523d4a2c356..0000000000000 --- a/shell/platform/android/android_context_vulkan_impeller.cc +++ /dev/null @@ -1,58 +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. - -#include "flutter/shell/platform/android/android_context_vulkan_impeller.h" - -#include "flutter/fml/paths.h" -#include "flutter/impeller/entity/vk/entity_shaders_vk.h" -#include "flutter/impeller/entity/vk/modern_shaders_vk.h" -#include "flutter/impeller/renderer/backend/vulkan/context_vk.h" -#include "flutter/impeller/scene/shaders/vk/scene_shaders_vk.h" - -namespace flutter { - -static std::shared_ptr CreateImpellerContext( - const fml::RefPtr& proc_table, - const std::shared_ptr& concurrent_loop, - bool enable_vulkan_validation) { - std::vector> shader_mappings = { - std::make_shared(impeller_entity_shaders_vk_data, - impeller_entity_shaders_vk_length), - std::make_shared(impeller_scene_shaders_vk_data, - impeller_scene_shaders_vk_length), - std::make_shared(impeller_modern_shaders_vk_data, - impeller_modern_shaders_vk_length), - }; - - PFN_vkGetInstanceProcAddr instance_proc_addr = - proc_table->NativeGetInstanceProcAddr(); - - impeller::ContextVK::Settings settings; - settings.proc_address_callback = instance_proc_addr; - settings.shader_libraries_data = std::move(shader_mappings); - settings.cache_directory = fml::paths::GetCachesDirectory(); - settings.worker_task_runner = concurrent_loop->GetTaskRunner(); - settings.enable_validation = enable_vulkan_validation; - return impeller::ContextVK::Create(std::move(settings)); -} - -AndroidContextVulkanImpeller::AndroidContextVulkanImpeller( - bool enable_validation) - : AndroidContext(AndroidRenderingAPI::kVulkan), - proc_table_(fml::MakeRefCounted()), - workers_(fml::ConcurrentMessageLoop::Create()) { - auto impeller_context = - CreateImpellerContext(proc_table_, workers_, enable_validation); - SetImpellerContext(impeller_context); - is_valid_ = - proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context; -} - -AndroidContextVulkanImpeller::~AndroidContextVulkanImpeller() = default; - -bool AndroidContextVulkanImpeller::IsValid() const { - return is_valid_; -} - -} // namespace flutter diff --git a/shell/platform/android/android_context_vulkan_impeller.h b/shell/platform/android/android_context_vulkan_impeller.h deleted file mode 100644 index 3fe5c627e593b..0000000000000 --- a/shell/platform/android/android_context_vulkan_impeller.h +++ /dev/null @@ -1,35 +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_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_ -#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_ - -#include "flutter/fml/concurrent_message_loop.h" -#include "flutter/fml/macros.h" -#include "flutter/impeller/toolkit/egl/display.h" -#include "flutter/shell/platform/android/context/android_context.h" -#include "flutter/vulkan/procs/vulkan_proc_table.h" - -namespace flutter { - -class AndroidContextVulkanImpeller : public AndroidContext { - public: - explicit AndroidContextVulkanImpeller(bool enable_validation); - - ~AndroidContextVulkanImpeller(); - - // |AndroidContext| - bool IsValid() const override; - - private: - fml::RefPtr proc_table_; - std::shared_ptr workers_; - bool is_valid_ = false; - - FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextVulkanImpeller); -}; - -} // namespace flutter - -#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_ diff --git a/shell/platform/android/android_surface_gl_impeller.cc b/shell/platform/android/android_surface_gl_impeller.cc index 662541ab64b55..ca4040ec5e6fc 100644 --- a/shell/platform/android/android_surface_gl_impeller.cc +++ b/shell/platform/android/android_surface_gl_impeller.cc @@ -5,21 +5,184 @@ #include "flutter/shell/platform/android/android_surface_gl_impeller.h" #include "flutter/fml/logging.h" +#include "flutter/impeller/renderer/backend/gles/context_gles.h" +#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h" +#include "flutter/impeller/toolkit/egl/context.h" #include "flutter/impeller/toolkit/egl/surface.h" #include "flutter/shell/gpu/gpu_surface_gl_impeller.h" +#include "impeller/entity/gles/entity_shaders_gles.h" +#include "impeller/scene/shaders/gles/scene_shaders_gles.h" namespace flutter { +class AndroidSurfaceGLImpeller::ReactorWorker final + : public impeller::ReactorGLES::Worker { + public: + ReactorWorker() = default; + + // |impeller::ReactorGLES::Worker| + ~ReactorWorker() override = default; + + // |impeller::ReactorGLES::Worker| + bool CanReactorReactOnCurrentThreadNow( + const impeller::ReactorGLES& reactor) const override { + impeller::ReaderLock lock(mutex_); + auto found = reactions_allowed_.find(std::this_thread::get_id()); + if (found == reactions_allowed_.end()) { + return false; + } + return found->second; + } + + void SetReactionsAllowedOnCurrentThread(bool allowed) { + impeller::WriterLock lock(mutex_); + reactions_allowed_[std::this_thread::get_id()] = allowed; + } + + private: + mutable impeller::RWMutex mutex_; + std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); +}; + +static std::shared_ptr CreateImpellerContext( + const std::shared_ptr& worker) { + auto proc_table = std::make_unique( + impeller::egl::CreateProcAddressResolver()); + + if (!proc_table->IsValid()) { + FML_LOG(ERROR) << "Could not create OpenGL proc table."; + return nullptr; + } + + std::vector> shader_mappings = { + std::make_shared( + impeller_entity_shaders_gles_data, + impeller_entity_shaders_gles_length), + std::make_shared( + impeller_scene_shaders_gles_data, impeller_scene_shaders_gles_length), + }; + + auto context = + impeller::ContextGLES::Create(std::move(proc_table), shader_mappings); + if (!context) { + FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; + return nullptr; + } + + if (!context->AddReactorWorker(worker).has_value()) { + FML_LOG(ERROR) << "Could not add reactor worker."; + return nullptr; + } + FML_LOG(ERROR) << "Using the Impeller rendering backend."; + return context; +} + AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( - const std::shared_ptr& android_context) - : android_context_(android_context) { - offscreen_surface_ = android_context_->CreateOffscreenSurface(); + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade) + : AndroidSurface(android_context), + reactor_worker_(std::shared_ptr(new ReactorWorker())) { + auto display = std::make_unique(); + if (!display->IsValid()) { + FML_DLOG(ERROR) << "Could not create EGL display."; + return; + } + + impeller::egl::ConfigDescriptor desc; + desc.api = impeller::egl::API::kOpenGLES2; + desc.color_format = impeller::egl::ColorFormat::kRGBA8888; + desc.depth_bits = impeller::egl::DepthBits::kZero; + desc.stencil_bits = impeller::egl::StencilBits::kEight; + desc.samples = impeller::egl::Samples::kFour; + + desc.surface_type = impeller::egl::SurfaceType::kWindow; + std::unique_ptr onscreen_config = + display->ChooseConfig(desc); + if (!onscreen_config) { + // Fallback for Android emulator. + desc.samples = impeller::egl::Samples::kOne; + onscreen_config = display->ChooseConfig(desc); + if (onscreen_config) { + FML_LOG(INFO) << "Warning: This device doesn't support MSAA for onscreen " + "framebuffers. Falling back to a single sample."; + } else { + FML_DLOG(ERROR) << "Could not choose onscreen config."; + return; + } + } + + desc.surface_type = impeller::egl::SurfaceType::kPBuffer; + auto offscreen_config = display->ChooseConfig(desc); + if (!offscreen_config) { + FML_DLOG(ERROR) << "Could not choose offscreen config."; + return; + } + + auto onscreen_context = display->CreateContext(*onscreen_config, nullptr); + if (!onscreen_context) { + FML_DLOG(ERROR) << "Could not create onscreen context."; + return; + } + + auto offscreen_context = + display->CreateContext(*offscreen_config, onscreen_context.get()); + if (!offscreen_context) { + FML_DLOG(ERROR) << "Could not create offscreen context."; + return; + } - if (!offscreen_surface_) { + auto offscreen_surface = + display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); + if (!offscreen_surface) { FML_DLOG(ERROR) << "Could not create offscreen surface."; return; } + if (!offscreen_context->MakeCurrent(*offscreen_surface)) { + FML_DLOG(ERROR) << "Could not make offscreen context current."; + return; + } + + auto impeller_context = CreateImpellerContext(reactor_worker_); + + if (!impeller_context) { + FML_DLOG(ERROR) << "Could not create Impeller context."; + return; + } + + if (!offscreen_context->ClearCurrent()) { + FML_DLOG(ERROR) << "Could not clear offscreen context."; + return; + } + + // Setup context listeners. + impeller::egl::Context::LifecycleListener listener = + [worker = + reactor_worker_](impeller::egl ::Context::LifecycleEvent event) { + switch (event) { + case impeller::egl::Context::LifecycleEvent::kDidMakeCurrent: + worker->SetReactionsAllowedOnCurrentThread(true); + break; + case impeller::egl::Context::LifecycleEvent::kWillClearCurrent: + worker->SetReactionsAllowedOnCurrentThread(false); + break; + } + }; + if (!onscreen_context->AddLifecycleListener(listener).has_value() || + !offscreen_context->AddLifecycleListener(listener).has_value()) { + FML_DLOG(ERROR) << "Could not add lifecycle listeners"; + } + + display_ = std::move(display); + onscreen_config_ = std::move(onscreen_config); + offscreen_config_ = std::move(offscreen_config); + offscreen_surface_ = std::move(offscreen_surface); + onscreen_context_ = std::move(onscreen_context); + offscreen_context_ = std::move(offscreen_context); + impeller_context_ = std::move(impeller_context); + // The onscreen surface will be acquired once the native window is set. is_valid_ = true; @@ -35,10 +198,10 @@ bool AndroidSurfaceGLImpeller::IsValid() const { // |AndroidSurface| std::unique_ptr AndroidSurfaceGLImpeller::CreateGPUSurface( GrDirectContext* gr_context) { - auto surface = std::make_unique( - this, // delegate - android_context_->GetImpellerContext() // context - ); + auto surface = + std::make_unique(this, // delegate + impeller_context_ // context + ); if (!surface->IsValid()) { return nullptr; } @@ -60,15 +223,20 @@ bool AndroidSurfaceGLImpeller::OnScreenSurfaceResize(const SkISize& size) { // |AndroidSurface| bool AndroidSurfaceGLImpeller::ResourceContextMakeCurrent() { - if (!offscreen_surface_) { + if (!offscreen_context_ || !offscreen_surface_) { return false; } - return android_context_->ResourceContextMakeCurrent(offscreen_surface_.get()); + + return offscreen_context_->MakeCurrent(*offscreen_surface_); } // |AndroidSurface| bool AndroidSurfaceGLImpeller::ResourceContextClearCurrent() { - return android_context_->ResourceContextClearCurrent(); + if (!offscreen_context_ || !offscreen_surface_) { + return false; + } + + return offscreen_context_->ClearCurrent(); } // |AndroidSurface| @@ -86,7 +254,7 @@ std::unique_ptr AndroidSurfaceGLImpeller::CreateSnapshotSurface() { // |AndroidSurface| std::shared_ptr AndroidSurfaceGLImpeller::GetImpellerContext() { - return android_context_->GetImpellerContext(); + return impeller_context_; } // |GPUSurfaceGLDelegate| @@ -96,20 +264,20 @@ AndroidSurfaceGLImpeller::GLContextMakeCurrent() { } bool AndroidSurfaceGLImpeller::OnGLContextMakeCurrent() { - if (!onscreen_surface_) { + if (!onscreen_surface_ || !onscreen_context_) { return false; } - return android_context_->OnscreenContextMakeCurrent(onscreen_surface_.get()); + return onscreen_context_->MakeCurrent(*onscreen_surface_); } // |GPUSurfaceGLDelegate| bool AndroidSurfaceGLImpeller::GLContextClearCurrent() { - if (!onscreen_surface_) { + if (!onscreen_surface_ || !onscreen_context_) { return false; } - return android_context_->OnscreenContextClearCurrent(); + return onscreen_context_->ClearCurrent(); } // |GPUSurfaceGLDelegate| @@ -158,8 +326,8 @@ bool AndroidSurfaceGLImpeller:: return false; } onscreen_surface_.reset(); - auto onscreen_surface = - android_context_->CreateOnscreenSurface(native_window_->handle()); + auto onscreen_surface = display_->CreateWindowSurface( + *onscreen_config_, native_window_->handle()); if (!onscreen_surface) { FML_DLOG(ERROR) << "Could not create onscreen surface."; return false; diff --git a/shell/platform/android/android_surface_gl_impeller.h b/shell/platform/android/android_surface_gl_impeller.h index 3066a8552ee25..b8ca423072f60 100644 --- a/shell/platform/android/android_surface_gl_impeller.h +++ b/shell/platform/android/android_surface_gl_impeller.h @@ -7,8 +7,8 @@ #include "flutter/fml/macros.h" #include "flutter/impeller/renderer/context.h" +#include "flutter/impeller/toolkit/egl/display.h" #include "flutter/shell/gpu/gpu_surface_gl_delegate.h" -#include "flutter/shell/platform/android/android_context_gl_impeller.h" #include "flutter/shell/platform/android/surface/android_native_window.h" #include "flutter/shell/platform/android/surface/android_surface.h" @@ -17,8 +17,9 @@ namespace flutter { class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, public AndroidSurface { public: - explicit AndroidSurfaceGLImpeller( - const std::shared_ptr& android_context); + AndroidSurfaceGLImpeller( + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade); // |AndroidSurface| ~AndroidSurfaceGLImpeller() override; @@ -73,9 +74,17 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, sk_sp GetGLInterface() const override; private: - std::shared_ptr android_context_; + class ReactorWorker; + + std::shared_ptr reactor_worker_; + std::unique_ptr display_; + std::unique_ptr onscreen_config_; + std::unique_ptr offscreen_config_; std::unique_ptr onscreen_surface_; std::unique_ptr offscreen_surface_; + std::unique_ptr onscreen_context_; + std::unique_ptr offscreen_context_; + std::shared_ptr impeller_context_; fml::RefPtr native_window_; bool is_valid_ = false; diff --git a/shell/platform/android/android_surface_gl_skia.cc b/shell/platform/android/android_surface_gl_skia.cc index d6ec0c3cf3d96..343d691e2ae75 100644 --- a/shell/platform/android/android_surface_gl_skia.cc +++ b/shell/platform/android/android_surface_gl_skia.cc @@ -21,13 +21,14 @@ constexpr char kEmulatorRendererPrefix[] = } // anonymous namespace AndroidSurfaceGLSkia::AndroidSurfaceGLSkia( - const std::shared_ptr& android_context) - : android_context_(android_context), + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade) + : AndroidSurface(android_context), native_window_(nullptr), onscreen_surface_(nullptr), offscreen_surface_(nullptr) { // Acquire the offscreen surface. - offscreen_surface_ = android_context_->CreateOffscreenSurface(); + offscreen_surface_ = GLContextPtr()->CreateOffscreenSurface(); if (!offscreen_surface_->IsValid()) { offscreen_surface_ = nullptr; } @@ -39,12 +40,12 @@ void AndroidSurfaceGLSkia::TeardownOnScreenContext() { // When the onscreen surface is destroyed, the context and the surface // instance should be deleted. Issue: // https://github.com/flutter/flutter/issues/64414 - android_context_->ClearCurrent(); + GLContextPtr()->ClearCurrent(); onscreen_surface_ = nullptr; } bool AndroidSurfaceGLSkia::IsValid() const { - return offscreen_surface_ && android_context_->IsValid(); + return offscreen_surface_ && GLContextPtr()->IsValid(); } std::unique_ptr AndroidSurfaceGLSkia::CreateGPUSurface( @@ -54,10 +55,10 @@ std::unique_ptr AndroidSurfaceGLSkia::CreateGPUSurface( true); } else { sk_sp main_skia_context = - android_context_->GetMainSkiaContext(); + GLContextPtr()->GetMainSkiaContext(); if (!main_skia_context) { main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this); - android_context_->SetMainSkiaContext(main_skia_context); + GLContextPtr()->SetMainSkiaContext(main_skia_context); } return std::make_unique(main_skia_context, this, true); } @@ -72,12 +73,12 @@ bool AndroidSurfaceGLSkia::OnScreenSurfaceResize(const SkISize& size) { return true; } - android_context_->ClearCurrent(); + GLContextPtr()->ClearCurrent(); // Ensure the destructor is called since it destroys the `EGLSurface` before // creating a new onscreen surface. onscreen_surface_ = nullptr; - onscreen_surface_ = android_context_->CreateOnscreenSurface(native_window_); + onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_); if (!onscreen_surface_->IsValid()) { FML_LOG(ERROR) << "Unable to create EGL window surface on resize."; return false; @@ -108,7 +109,7 @@ bool AndroidSurfaceGLSkia::SetNativeWindow( // creating a new onscreen surface. onscreen_surface_ = nullptr; // Create the onscreen surface. - onscreen_surface_ = android_context_->CreateOnscreenSurface(window); + onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(window); if (!onscreen_surface_->IsValid()) { return false; } @@ -126,7 +127,7 @@ std::unique_ptr AndroidSurfaceGLSkia::GLContextMakeCurrent() { bool AndroidSurfaceGLSkia::GLContextClearCurrent() { FML_DCHECK(IsValid()); - return android_context_->ClearCurrent(); + return GLContextPtr()->ClearCurrent(); } SurfaceFrame::FramebufferInfo AndroidSurfaceGLSkia::GLContextFramebufferInfo() @@ -185,7 +186,7 @@ sk_sp AndroidSurfaceGLSkia::GetGLInterface() const { reinterpret_cast(glGetString(GL_RENDERER)); if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix, strlen(kEmulatorRendererPrefix)) == 0) { - EGLContext new_context = android_context_->CreateNewContext(); + EGLContext new_context = GLContextPtr()->CreateNewContext(); if (new_context != EGL_NO_CONTEXT) { EGLContext old_context = eglGetCurrentContext(); EGLDisplay display = eglGetCurrentDisplay(); @@ -204,15 +205,19 @@ sk_sp AndroidSurfaceGLSkia::GetGLInterface() const { return GPUSurfaceGLDelegate::GetGLInterface(); } +AndroidContextGLSkia* AndroidSurfaceGLSkia::GLContextPtr() const { + return reinterpret_cast(android_context_.get()); +} + std::unique_ptr AndroidSurfaceGLSkia::CreateSnapshotSurface() { if (!onscreen_surface_ || !onscreen_surface_->IsValid()) { - onscreen_surface_ = android_context_->CreatePbufferSurface(); + onscreen_surface_ = GLContextPtr()->CreatePbufferSurface(); } sk_sp main_skia_context = - android_context_->GetMainSkiaContext(); + GLContextPtr()->GetMainSkiaContext(); if (!main_skia_context) { main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this); - android_context_->SetMainSkiaContext(main_skia_context); + GLContextPtr()->SetMainSkiaContext(main_skia_context); } return std::make_unique(main_skia_context, this, true); diff --git a/shell/platform/android/android_surface_gl_skia.h b/shell/platform/android/android_surface_gl_skia.h index 1c35692dc3a0e..274c28f2c6760 100644 --- a/shell/platform/android/android_surface_gl_skia.h +++ b/shell/platform/android/android_surface_gl_skia.h @@ -21,8 +21,9 @@ namespace flutter { class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate, public AndroidSurface { public: - explicit AndroidSurfaceGLSkia( - const std::shared_ptr& android_context); + AndroidSurfaceGLSkia( + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade); ~AndroidSurfaceGLSkia() override; @@ -81,11 +82,16 @@ class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate, } private: - std::shared_ptr android_context_; fml::RefPtr native_window_; std::unique_ptr onscreen_surface_; std::unique_ptr offscreen_surface_; + //---------------------------------------------------------------------------- + /// @brief Takes the super class AndroidSurface's AndroidContext and + /// return a raw pointer to an AndroidContextGL. + /// + AndroidContextGLSkia* GLContextPtr() const; + FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceGLSkia); }; diff --git a/shell/platform/android/android_surface_software.cc b/shell/platform/android/android_surface_software.cc index 0d1a2d9e2c180..fdfc8d9d509ac 100644 --- a/shell/platform/android/android_surface_software.cc +++ b/shell/platform/android/android_surface_software.cc @@ -40,7 +40,10 @@ bool GetSkColorType(int32_t buffer_format, } // anonymous namespace -AndroidSurfaceSoftware::AndroidSurfaceSoftware() { +AndroidSurfaceSoftware::AndroidSurfaceSoftware( + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade) + : AndroidSurface(android_context) { GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_, &target_alpha_type_); } diff --git a/shell/platform/android/android_surface_software.h b/shell/platform/android/android_surface_software.h index 1b7083aa7dda1..38e4c498f3843 100644 --- a/shell/platform/android/android_surface_software.h +++ b/shell/platform/android/android_surface_software.h @@ -19,7 +19,9 @@ namespace flutter { class AndroidSurfaceSoftware final : public AndroidSurface, public GPUSurfaceSoftwareDelegate { public: - AndroidSurfaceSoftware(); + AndroidSurfaceSoftware( + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade); ~AndroidSurfaceSoftware() override; diff --git a/shell/platform/android/android_surface_vulkan_impeller.cc b/shell/platform/android/android_surface_vulkan_impeller.cc index e5d2416af90bb..0e5ac734e3b89 100644 --- a/shell/platform/android/android_surface_vulkan_impeller.cc +++ b/shell/platform/android/android_surface_vulkan_impeller.cc @@ -10,16 +10,52 @@ #include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/logging.h" #include "flutter/fml/memory/ref_ptr.h" +#include "flutter/fml/paths.h" #include "flutter/impeller/renderer/backend/vulkan/context_vk.h" #include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h" #include "flutter/vulkan/vulkan_native_surface_android.h" +#include "impeller/entity/vk/entity_shaders_vk.h" +#include "impeller/entity/vk/modern_shaders_vk.h" +#include "impeller/scene/shaders/vk/scene_shaders_vk.h" namespace flutter { +static std::shared_ptr CreateImpellerContext( + const fml::RefPtr& proc_table, + const std::shared_ptr& concurrent_loop, + bool enable_vulkan_validation) { + std::vector> shader_mappings = { + std::make_shared(impeller_entity_shaders_vk_data, + impeller_entity_shaders_vk_length), + std::make_shared(impeller_scene_shaders_vk_data, + impeller_scene_shaders_vk_length), + std::make_shared(impeller_modern_shaders_vk_data, + impeller_modern_shaders_vk_length), + }; + + PFN_vkGetInstanceProcAddr instance_proc_addr = + proc_table->NativeGetInstanceProcAddr(); + + impeller::ContextVK::Settings settings; + settings.proc_address_callback = instance_proc_addr; + settings.shader_libraries_data = std::move(shader_mappings); + settings.cache_directory = fml::paths::GetCachesDirectory(); + settings.worker_task_runner = concurrent_loop->GetTaskRunner(); + settings.enable_validation = enable_vulkan_validation; + return impeller::ContextVK::Create(std::move(settings)); +} + AndroidSurfaceVulkanImpeller::AndroidSurfaceVulkanImpeller( - const std::shared_ptr& android_context) - : android_context_(android_context) { - is_valid_ = android_context_->IsValid(); + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade, + bool enable_vulkan_validation) + : AndroidSurface(android_context), + proc_table_(fml::MakeRefCounted()), + workers_(fml::ConcurrentMessageLoop::Create()) { + impeller_context_ = + CreateImpellerContext(proc_table_, workers_, enable_vulkan_validation); + is_valid_ = + proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context_; } AndroidSurfaceVulkanImpeller::~AndroidSurfaceVulkanImpeller() = default; @@ -43,8 +79,7 @@ std::unique_ptr AndroidSurfaceVulkanImpeller::CreateGPUSurface( } std::unique_ptr gpu_surface = - std::make_unique( - android_context_->GetImpellerContext()); + std::make_unique(impeller_context_); if (!gpu_surface->IsValid()) { return nullptr; @@ -70,8 +105,7 @@ bool AndroidSurfaceVulkanImpeller::SetNativeWindow( native_window_ = std::move(window); bool success = native_window_ && native_window_->IsValid(); if (success) { - auto& context_vk = - impeller::ContextVK::Cast(*android_context_->GetImpellerContext()); + auto& context_vk = impeller::ContextVK::Cast(*impeller_context_); auto surface = context_vk.CreateAndroidSurface(native_window_->handle()); if (!surface) { @@ -88,7 +122,7 @@ bool AndroidSurfaceVulkanImpeller::SetNativeWindow( std::shared_ptr AndroidSurfaceVulkanImpeller::GetImpellerContext() { - return android_context_->GetImpellerContext(); + return impeller_context_; } } // namespace flutter diff --git a/shell/platform/android/android_surface_vulkan_impeller.h b/shell/platform/android/android_surface_vulkan_impeller.h index 548a0a5a4cf69..3fff43d9d974c 100644 --- a/shell/platform/android/android_surface_vulkan_impeller.h +++ b/shell/platform/android/android_surface_vulkan_impeller.h @@ -7,16 +7,18 @@ #include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/macros.h" #include "flutter/impeller/renderer/context.h" -#include "flutter/shell/platform/android/android_context_vulkan_impeller.h" #include "flutter/shell/platform/android/surface/android_native_window.h" #include "flutter/shell/platform/android/surface/android_surface.h" +#include "flutter/vulkan/procs/vulkan_proc_table.h" namespace flutter { class AndroidSurfaceVulkanImpeller : public AndroidSurface { public: - explicit AndroidSurfaceVulkanImpeller( - const std::shared_ptr& android_context); + AndroidSurfaceVulkanImpeller( + const std::shared_ptr& android_context, + const std::shared_ptr& jni_facade, + bool enable_vulkan_validation); ~AndroidSurfaceVulkanImpeller() override; @@ -46,8 +48,10 @@ class AndroidSurfaceVulkanImpeller : public AndroidSurface { bool SetNativeWindow(fml::RefPtr window) override; private: - std::shared_ptr android_context_; + fml::RefPtr proc_table_; fml::RefPtr native_window_; + std::shared_ptr workers_; + std::shared_ptr impeller_context_; bool is_valid_ = false; FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceVulkanImpeller); diff --git a/shell/platform/android/context/BUILD.gn b/shell/platform/android/context/BUILD.gn index a75549cab04d5..89918491187d3 100644 --- a/shell/platform/android/context/BUILD.gn +++ b/shell/platform/android/context/BUILD.gn @@ -15,7 +15,6 @@ source_set("context") { deps = [ "//flutter/fml", - "//flutter/impeller/renderer", "//third_party/skia", ] diff --git a/shell/platform/android/context/android_context.cc b/shell/platform/android/context/android_context.cc index 3d7c4e619d97b..1d4badf9543b7 100644 --- a/shell/platform/android/context/android_context.cc +++ b/shell/platform/android/context/android_context.cc @@ -32,13 +32,4 @@ sk_sp AndroidContext::GetMainSkiaContext() const { return main_context_; } -std::shared_ptr AndroidContext::GetImpellerContext() const { - return impeller_context_; -} - -void AndroidContext::SetImpellerContext( - const std::shared_ptr& context) { - impeller_context_ = context; -} - } // namespace flutter diff --git a/shell/platform/android/context/android_context.h b/shell/platform/android/context/android_context.h index ac3b7d49dee8a..0bed23e398674 100644 --- a/shell/platform/android/context/android_context.h +++ b/shell/platform/android/context/android_context.h @@ -7,7 +7,6 @@ #include "flutter/fml/macros.h" #include "flutter/fml/task_runner.h" -#include "flutter/impeller/renderer/context.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { @@ -15,7 +14,6 @@ namespace flutter { enum class AndroidRenderingAPI { kSoftware, kOpenGLES, - kVulkan, }; //------------------------------------------------------------------------------ @@ -56,25 +54,12 @@ class AndroidContext { /// sk_sp GetMainSkiaContext() const; - //---------------------------------------------------------------------------- - /// @brief Accessor for the Impeller context associated with - /// AndroidSurfaces and the raster thread. - /// - std::shared_ptr GetImpellerContext() const; - - protected: - /// Intended to be called from a subclass constructor after setup work for the - /// context has completed. - void SetImpellerContext(const std::shared_ptr& context); - private: const AndroidRenderingAPI rendering_api_; // This is the Skia context used for on-screen rendering. sk_sp main_context_; - std::shared_ptr impeller_context_; - FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext); }; diff --git a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc index c2d90ae2b10de..b9c527b16c710 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc @@ -264,7 +264,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [gr_context, window, frame_size, framebuffer_info]() { + [&android_context, gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -284,7 +284,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { .WillOnce(Return(ByMove(std::move(surface_frame_1)))) .WillOnce(Return(ByMove(std::move(surface_frame_2)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -471,7 +472,7 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [gr_context, window, frame_size, framebuffer_info]() { + [&android_context, gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -484,7 +485,8 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) { .Times(1 /* frames */) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -569,7 +571,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [gr_context, window, frame_size, framebuffer_info]() { + [&android_context, gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -582,7 +584,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) { .Times(1 /* frames */) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -672,7 +675,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [gr_context, window, frame_size, framebuffer_info]() { + [&android_context, gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -685,7 +688,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) { .Times(1 /* frames */) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -760,7 +764,7 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [gr_context, window, frame_size, framebuffer_info]() { + [&android_context, gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -772,7 +776,8 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -848,7 +853,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { auto frame_size = SkISize::Make(1000, 1000); SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_factory = std::make_shared( - [gr_context, window, frame_size, framebuffer_info]() { + [&android_context, gr_context, window, frame_size, framebuffer_info]() { auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { @@ -860,7 +865,8 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) @@ -972,7 +978,7 @@ TEST(AndroidExternalViewEmbedder, Teardown) { auto gr_context = GrDirectContext::MakeMock(nullptr); auto frame_size = SkISize::Make(1000, 1000); auto surface_factory = std::make_shared( - [gr_context, window, frame_size]() { + [&android_context, gr_context, window, frame_size]() { SurfaceFrame::FramebufferInfo framebuffer_info; auto surface_frame_1 = std::make_unique( SkSurface::MakeNull(1000, 1000), framebuffer_info, @@ -985,7 +991,8 @@ TEST(AndroidExternalViewEmbedder, Teardown) { EXPECT_CALL(*surface_mock, AcquireFrame(frame_size)) .WillOnce(Return(ByMove(std::move(surface_frame_1)))); - auto android_surface_mock = std::make_unique(); + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())) .WillOnce(Return(ByMove(std::move(surface_mock)))); diff --git a/shell/platform/android/external_view_embedder/surface_pool_unittests.cc b/shell/platform/android/external_view_embedder/surface_pool_unittests.cc index d0c505675fe09..ecf4e1a6c78e9 100644 --- a/shell/platform/android/external_view_embedder/surface_pool_unittests.cc +++ b/shell/platform/android/external_view_embedder/surface_pool_unittests.cc @@ -50,9 +50,10 @@ TEST(SurfacePool, GetLayerAllocateOneLayer) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -81,9 +82,10 @@ TEST(SurfacePool, GetUnusedLayers) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -116,8 +118,9 @@ TEST(SurfacePool, GetLayerRecycle) { auto gr_context_2 = GrDirectContext::MakeMock(nullptr); auto surface_factory = std::make_shared( - [gr_context_1, gr_context_2, window]() { - auto android_surface_mock = std::make_unique(); + [&android_context, gr_context_1, gr_context_2, window]() { + auto android_surface_mock = + std::make_unique(android_context); // Allocate two GPU surfaces for each gr context. EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context_1.get())); @@ -163,9 +166,10 @@ TEST(SurfacePool, GetLayerAllocateTwoLayers) { ByMove(std::make_unique( 1, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -202,9 +206,10 @@ TEST(SurfacePool, DestroyLayers) { ByMove(std::make_unique( 0, window)))); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); @@ -231,9 +236,10 @@ TEST(SurfacePool, DestroyLayersFrameSizeChanged) { auto window = fml::MakeRefCounted(nullptr); - auto surface_factory = - std::make_shared([gr_context, window]() { - auto android_surface_mock = std::make_unique(); + auto surface_factory = std::make_shared( + [&android_context, gr_context, window]() { + auto android_surface_mock = + std::make_unique(android_context); EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get())); EXPECT_CALL(*android_surface_mock, SetNativeWindow(window)); EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true)); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 1ee2c8926b302..804b0f111de7b 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -31,29 +31,36 @@ namespace flutter { AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl( const std::shared_ptr& context, - bool enable_impeller) - : android_context_(context), enable_impeller_(enable_impeller) {} + std::shared_ptr jni_facade, + bool enable_impeller, + bool enable_vulkan_validation) + : android_context_(context), + jni_facade_(std::move(jni_facade)), + enable_impeller_(enable_impeller), + enable_vulkan_validation_(enable_vulkan_validation) {} AndroidSurfaceFactoryImpl::~AndroidSurfaceFactoryImpl() = default; std::unique_ptr AndroidSurfaceFactoryImpl::CreateSurface() { switch (android_context_->RenderingApi()) { case AndroidRenderingAPI::kSoftware: - return std::make_unique(); + return std::make_unique(android_context_, + jni_facade_); case AndroidRenderingAPI::kOpenGLES: if (enable_impeller_) { - return std::make_unique( - std::static_pointer_cast( - android_context_)); +// TODO(kaushikiska@): Enable this after wiring a preference for Vulkan backend. +#if false + return std::make_unique( + android_context_, jni_facade_, enable_vulkan_validation_); + +#else + return std::make_unique(android_context_, + jni_facade_); +#endif } else { - return std::make_unique( - std::static_pointer_cast(android_context_)); + return std::make_unique(android_context_, + jni_facade_); } - case AndroidRenderingAPI::kVulkan: - FML_DCHECK(enable_impeller_); - return std::make_unique( - std::static_pointer_cast( - android_context_)); default: FML_DCHECK(false); return nullptr; @@ -64,19 +71,12 @@ static std::shared_ptr CreateAndroidContext( bool use_software_rendering, const flutter::TaskRunners& task_runners, uint8_t msaa_samples, - bool enable_impeller, - bool enable_vulkan_validation) { + bool enable_impeller) { if (use_software_rendering) { return std::make_shared(AndroidRenderingAPI::kSoftware); } if (enable_impeller) { - // TODO(kaushikiska@): Enable this after wiring a preference for Vulkan - // backend. -#if false - return std::make_unique(enable_vulkan_validation); -#else return std::make_unique(); -#endif } return std::make_unique( AndroidRenderingAPI::kOpenGLES, // @@ -100,8 +100,7 @@ PlatformViewAndroid::PlatformViewAndroid( use_software_rendering, task_runners, msaa_samples, - delegate.OnPlatformViewGetSettings().enable_impeller, - delegate.OnPlatformViewGetSettings().enable_vulkan_validation)) {} + delegate.OnPlatformViewGetSettings().enable_impeller)) {} PlatformViewAndroid::PlatformViewAndroid( PlatformView::Delegate& delegate, @@ -117,8 +116,10 @@ PlatformViewAndroid::PlatformViewAndroid( FML_CHECK(android_context_->IsValid()) << "Could not create surface from invalid Android context."; surface_factory_ = std::make_shared( - android_context_, // - delegate.OnPlatformViewGetSettings().enable_impeller // + android_context_, // + jni_facade_, // + delegate.OnPlatformViewGetSettings().enable_impeller, // + delegate.OnPlatformViewGetSettings().enable_vulkan_validation // ); android_surface_ = surface_factory_->CreateSurface(); FML_CHECK(android_surface_ && android_surface_->IsValid()) diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 069b2f920b3af..d7a8e8ce65751 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -27,7 +27,9 @@ namespace flutter { class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory { public: AndroidSurfaceFactoryImpl(const std::shared_ptr& context, - bool enable_impeller); + std::shared_ptr jni_facade, + bool enable_impeller, + bool enable_vulkan_validation); ~AndroidSurfaceFactoryImpl() override; @@ -35,7 +37,9 @@ class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory { private: const std::shared_ptr& android_context_; + std::shared_ptr jni_facade_; const bool enable_impeller_; + const bool enable_vulkan_validation_; }; class PlatformViewAndroid final : public PlatformView { diff --git a/shell/platform/android/surface/android_surface.cc b/shell/platform/android/surface/android_surface.cc index e301491b5fce0..ab96387edbd77 100644 --- a/shell/platform/android/surface/android_surface.cc +++ b/shell/platform/android/surface/android_surface.cc @@ -7,7 +7,11 @@ namespace flutter { -AndroidSurface::AndroidSurface() = default; +AndroidSurface::AndroidSurface( + const std::shared_ptr& android_context) { + FML_DCHECK(android_context->IsValid()); + android_context_ = android_context; +} AndroidSurface::~AndroidSurface() = default; diff --git a/shell/platform/android/surface/android_surface.h b/shell/platform/android/surface/android_surface.h index 7eae6c68e7d71..485f619e1a81b 100644 --- a/shell/platform/android/surface/android_surface.h +++ b/shell/platform/android/surface/android_surface.h @@ -46,7 +46,9 @@ class AndroidSurface { virtual std::shared_ptr GetImpellerContext(); protected: - AndroidSurface(); + explicit AndroidSurface( + const std::shared_ptr& android_context); + std::shared_ptr android_context_; }; class AndroidSurfaceFactory { diff --git a/shell/platform/android/surface/android_surface_mock.cc b/shell/platform/android/surface/android_surface_mock.cc index 0f7c6d1a6d80c..8f718fcae667a 100644 --- a/shell/platform/android/surface/android_surface_mock.cc +++ b/shell/platform/android/surface/android_surface_mock.cc @@ -6,6 +6,10 @@ namespace flutter { +AndroidSurfaceMock::AndroidSurfaceMock( + const std::shared_ptr& android_context) + : AndroidSurface(android_context) {} + std::unique_ptr AndroidSurfaceMock::GLContextMakeCurrent() { return std::make_unique(/*static_result=*/true); } diff --git a/shell/platform/android/surface/android_surface_mock.h b/shell/platform/android/surface/android_surface_mock.h index 411816698cb74..3f326a21920b7 100644 --- a/shell/platform/android/surface/android_surface_mock.h +++ b/shell/platform/android/surface/android_surface_mock.h @@ -18,6 +18,9 @@ namespace flutter { class AndroidSurfaceMock final : public GPUSurfaceGLDelegate, public AndroidSurface { public: + explicit AndroidSurfaceMock( + const std::shared_ptr& android_context); + MOCK_METHOD(bool, IsValid, (), (const, override)); MOCK_METHOD(void, TeardownOnScreenContext, (), (override)); From d54a18e24ab967c0a1f3ec6e942b838b2ef63734 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 13 Apr 2023 13:48:07 -0700 Subject: [PATCH 9/9] Update shell/common/rasterizer.cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com> --- shell/common/rasterizer.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index c9d2e0ddb6876..3b01c5c9bb0a9 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -52,6 +52,7 @@ fml::TaskRunnerAffineWeakPtr Rasterizer::GetSnapshotDelegate() const { return weak_factory_.GetWeakPtr(); } + void Rasterizer::SetImpellerContext( std::weak_ptr impeller_context) { impeller_context_ = std::move(impeller_context);