From 960ccb85e86cd20e92caccb0ab697be160a1b1ea Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Apr 2023 16:56:11 -0700 Subject: [PATCH 01/12] 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 02/12] 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 03/12] 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 04/12] 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 05/12] 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 06/12] 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 07/12] 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 17564eeeedd55e269ab3f1c52e42b56321442551 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 13 Apr 2023 20:10:27 -0700 Subject: [PATCH 08/12] Update rasterizer.cc --- shell/common/rasterizer.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index af7796e907164..3b01c5c9bb0a9 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -52,10 +52,6 @@ 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::SetImpellerContext( std::weak_ptr impeller_context) { From 924b2a05acc7bb58c60ed333b133e62e7ea95542 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 11 May 2023 20:56:07 -0700 Subject: [PATCH 09/12] bad merge --- .../android/android_surface_gl_impeller.cc | 105 ------------------ .../android/android_surface_gl_impeller.h | 6 +- 2 files changed, 2 insertions(+), 109 deletions(-) diff --git a/shell/platform/android/android_surface_gl_impeller.cc b/shell/platform/android/android_surface_gl_impeller.cc index 9636f03febae8..662541ab64b55 100644 --- a/shell/platform/android/android_surface_gl_impeller.cc +++ b/shell/platform/android/android_surface_gl_impeller.cc @@ -11,120 +11,15 @@ namespace flutter { AndroidSurfaceGLImpeller::AndroidSurfaceGLImpeller( -<<<<<<< HEAD const std::shared_ptr& android_context) : android_context_(android_context) { offscreen_surface_ = android_context_->CreateOffscreenSurface(); if (!offscreen_surface_) { -======= - const std::shared_ptr& android_context, - const std::shared_ptr& jni_facade, - std::unique_ptr display) - : AndroidSurface(android_context), - reactor_worker_(std::shared_ptr(new ReactorWorker())), - display_(std::move(display)) { - if (!display_->IsValid()) { - FML_DLOG(ERROR) << "Could not create surface with invalid 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; - } - - auto offscreen_surface = - display_->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); - if (!offscreen_surface) { ->>>>>>> upstream/main FML_DLOG(ERROR) << "Could not create offscreen surface."; return; } -<<<<<<< HEAD -======= - 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"; - } - - 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); - ->>>>>>> upstream/main // The onscreen surface will be acquired once the native window is set. is_valid_ = true; diff --git a/shell/platform/android/android_surface_gl_impeller.h b/shell/platform/android/android_surface_gl_impeller.h index 3a51283155a3e..05d91972e4d63 100644 --- a/shell/platform/android/android_surface_gl_impeller.h +++ b/shell/platform/android/android_surface_gl_impeller.h @@ -17,10 +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, - std::unique_ptr display); + explicit AndroidSurfaceGLImpeller( + const std::shared_ptr& android_context); // |AndroidSurface| ~AndroidSurfaceGLImpeller() override; From 2004313a6d8b41ed13a3a5da1db57fae0ffecbea Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 11 May 2023 21:44:45 -0700 Subject: [PATCH 10/12] fixes for https://github.com/flutter/engine/pull/40979 --- shell/platform/android/BUILD.gn | 2 +- .../android/android_context_gl_impeller.cc | 14 +++++------ .../android/android_context_gl_impeller.h | 3 ++- ... android_context_gl_impeller_unittests.cc} | 23 ++++++------------- .../android/android_surface_gl_impeller.h | 2 +- .../platform/android/platform_view_android.cc | 3 ++- 6 files changed, 20 insertions(+), 27 deletions(-) rename shell/platform/android/{android_surface_gl_impeller_unittests.cc => android_context_gl_impeller_unittests.cc} (78%) diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 456258cc9dac6..f42e052fa3343 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -39,9 +39,9 @@ executable("flutter_shell_native_unittests") { visibility = [ "*" ] testonly = true sources = [ + "android_context_gl_impeller_unittests.cc", "android_context_gl_unittests.cc", "android_shell_holder_unittests.cc", - "android_surface_gl_impeller_unittests.cc", "apk_asset_provider_unittests.cc", "flutter_shell_native_unittests.cc", ] diff --git a/shell/platform/android/android_context_gl_impeller.cc b/shell/platform/android/android_context_gl_impeller.cc index f2526596b9dbb..4a8dab08ccc9f 100644 --- a/shell/platform/android/android_context_gl_impeller.cc +++ b/shell/platform/android/android_context_gl_impeller.cc @@ -79,12 +79,13 @@ static std::shared_ptr CreateImpellerContext( return context; } -AndroidContextGLImpeller::AndroidContextGLImpeller() +AndroidContextGLImpeller::AndroidContextGLImpeller( + std::unique_ptr display) : 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."; + reactor_worker_(std::shared_ptr(new ReactorWorker())), + display_(std::move(display)) { + if (!display_->IsValid()) { + FML_DLOG(ERROR) << "Could not create context with invalid EGL display."; return; } @@ -97,7 +98,7 @@ AndroidContextGLImpeller::AndroidContextGLImpeller() desc.surface_type = impeller::egl::SurfaceType::kWindow; std::unique_ptr onscreen_config = - display->ChooseConfig(desc); + display_->ChooseConfig(desc); if (!onscreen_config) { // Fallback for Android emulator. desc.samples = impeller::egl::Samples::kOne; @@ -169,7 +170,6 @@ AndroidContextGLImpeller::AndroidContextGLImpeller() 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); diff --git a/shell/platform/android/android_context_gl_impeller.h b/shell/platform/android/android_context_gl_impeller.h index 294ce8036afb6..90466db683a8a 100644 --- a/shell/platform/android/android_context_gl_impeller.h +++ b/shell/platform/android/android_context_gl_impeller.h @@ -13,7 +13,8 @@ namespace flutter { class AndroidContextGLImpeller : public AndroidContext { public: - AndroidContextGLImpeller(); + explicit AndroidContextGLImpeller( + std::unique_ptr display); ~AndroidContextGLImpeller(); diff --git a/shell/platform/android/android_surface_gl_impeller_unittests.cc b/shell/platform/android/android_context_gl_impeller_unittests.cc similarity index 78% rename from shell/platform/android/android_surface_gl_impeller_unittests.cc rename to shell/platform/android/android_context_gl_impeller_unittests.cc index 37f11aaa3f1cf..a3dace6e68c7d 100644 --- a/shell/platform/android/android_surface_gl_impeller_unittests.cc +++ b/shell/platform/android/android_context_gl_impeller_unittests.cc @@ -1,5 +1,4 @@ -#include "flutter/shell/platform/android/android_surface_gl_impeller.h" -#include "flutter/shell/platform/android/jni/jni_mock.h" +#include "flutter/shell/platform/android/android_context_gl_impeller.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -24,10 +23,7 @@ class MockDisplay : public impeller::egl::Display { }; } // namespace -TEST(AndroidSurfaceGLImpeller, MSAAFirstAttempt) { - auto context = - std::make_shared(AndroidRenderingAPI::kSoftware); - auto jni = std::make_shared(); +TEST(AndroidContextGLImpeller, MSAAFirstAttempt) { auto display = std::make_unique(); EXPECT_CALL(*display, IsValid).WillRepeatedly(Return(true)); auto first_result = std::make_unique(ConfigDescriptor(), EGLConfig()); @@ -46,15 +42,11 @@ TEST(AndroidSurfaceGLImpeller, MSAAFirstAttempt) { .WillOnce(Return(ByMove(std::move(second_result)))); ON_CALL(*display, ChooseConfig(_)) .WillByDefault(Return(ByMove(std::unique_ptr()))); - auto surface = std::make_unique(context, jni, - std::move(display)); - ASSERT_TRUE(surface); + auto context = std::make_unique(std::move(display)); + ASSERT_TRUE(context); } -TEST(AndroidSurfaceGLImpeller, FallbackForEmulator) { - auto context = - std::make_shared(AndroidRenderingAPI::kSoftware); - auto jni = std::make_shared(); +TEST(AndroidContextGLImpeller, FallbackForEmulator) { auto display = std::make_unique(); EXPECT_CALL(*display, IsValid).WillRepeatedly(Return(true)); std::unique_ptr first_result; @@ -81,9 +73,8 @@ TEST(AndroidSurfaceGLImpeller, FallbackForEmulator) { .WillOnce(Return(ByMove(std::move(third_result)))); ON_CALL(*display, ChooseConfig(_)) .WillByDefault(Return(ByMove(std::unique_ptr()))); - auto surface = std::make_unique(context, jni, - std::move(display)); - ASSERT_TRUE(surface); + auto context = std::make_unique(std::move(display)); + ASSERT_TRUE(context); } } // namespace testing } // namespace flutter diff --git a/shell/platform/android/android_surface_gl_impeller.h b/shell/platform/android/android_surface_gl_impeller.h index 05d91972e4d63..3066a8552ee25 100644 --- a/shell/platform/android/android_surface_gl_impeller.h +++ b/shell/platform/android/android_surface_gl_impeller.h @@ -18,7 +18,7 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate, public AndroidSurface { public: explicit AndroidSurfaceGLImpeller( - const std::shared_ptr& android_context); + const std::shared_ptr& android_context); // |AndroidSurface| ~AndroidSurfaceGLImpeller() override; diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 1ee2c8926b302..769f1a0feae8f 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -75,7 +75,8 @@ static std::shared_ptr CreateAndroidContext( #if false return std::make_unique(enable_vulkan_validation); #else - return std::make_unique(); + return std::make_unique( + std::make_unique()); #endif } return std::make_unique( From 6a17fc5aa9fd100bca355e38684d3c420773efba Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 11 May 2023 23:16:57 -0700 Subject: [PATCH 11/12] fix var name --- .../platform/android/android_context_gl_impeller.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/platform/android/android_context_gl_impeller.cc b/shell/platform/android/android_context_gl_impeller.cc index 4a8dab08ccc9f..a4bcd9fbc7f5c 100644 --- a/shell/platform/android/android_context_gl_impeller.cc +++ b/shell/platform/android/android_context_gl_impeller.cc @@ -4,7 +4,6 @@ #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" @@ -84,7 +83,7 @@ AndroidContextGLImpeller::AndroidContextGLImpeller( : AndroidContext(AndroidRenderingAPI::kOpenGLES), reactor_worker_(std::shared_ptr(new ReactorWorker())), display_(std::move(display)) { - if (!display_->IsValid()) { + if (!display_ || !display_->IsValid()) { FML_DLOG(ERROR) << "Could not create context with invalid EGL display."; return; } @@ -102,7 +101,7 @@ AndroidContextGLImpeller::AndroidContextGLImpeller( if (!onscreen_config) { // Fallback for Android emulator. desc.samples = impeller::egl::Samples::kOne; - onscreen_config = display->ChooseConfig(desc); + 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."; @@ -113,20 +112,20 @@ AndroidContextGLImpeller::AndroidContextGLImpeller( } desc.surface_type = impeller::egl::SurfaceType::kPBuffer; - auto offscreen_config = display->ChooseConfig(desc); + 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); + 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()); + display_->CreateContext(*offscreen_config, onscreen_context.get()); if (!offscreen_context) { FML_DLOG(ERROR) << "Could not create offscreen context."; return; @@ -135,7 +134,7 @@ AndroidContextGLImpeller::AndroidContextGLImpeller( // Creating the impeller::Context requires a current context, which requires // some surface. auto offscreen_surface = - display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); + display_->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); if (!offscreen_context->MakeCurrent(*offscreen_surface)) { FML_DLOG(ERROR) << "Could not make offscreen context current."; return; From ba0f0f07cfccfab40bdb778f33ea61f8f3befa8e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 11 May 2023 23:28:11 -0700 Subject: [PATCH 12/12] licenses --- ci/licenses_golden/excluded_files | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 2499aea6902af..ef69cbb78849f 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -226,9 +226,9 @@ ../../../flutter/shell/common/variable_refresh_rate_display_unittests.cc ../../../flutter/shell/common/vsync_waiter_unittests.cc ../../../flutter/shell/platform/android/.gitignore +../../../flutter/shell/platform/android/android_context_gl_impeller_unittests.cc ../../../flutter/shell/platform/android/android_context_gl_unittests.cc ../../../flutter/shell/platform/android/android_shell_holder_unittests.cc -../../../flutter/shell/platform/android/android_surface_gl_impeller_unittests.cc ../../../flutter/shell/platform/android/apk_asset_provider_unittests.cc ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc ../../../flutter/shell/platform/android/external_view_embedder/surface_pool_unittests.cc