[Impeller] [Android] Refactor the Android context/surface implementation to work more like Skia. (flutter/engine#41059)

Noticed this while working on  https://github.com/flutter/flutter/issues/124181

In Impeller right now, Android creates a context for each surface - but in Skia, Android creates one context and shares it across surfaces. For the multiple-engine scenario this matters. This also makes it possible for Android to provide the impeller::Context independently of surface creation.
This commit is contained in:
Dan Field
2023-05-12 00:10:05 -07:00
committed by GitHub
parent dcc6e318f8
commit 29c5e7808b
28 changed files with 486 additions and 453 deletions

View File

@@ -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

View File

@@ -2226,6 +2226,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
@@ -4843,6 +4845,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

View File

@@ -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",
]
@@ -72,6 +72,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",

View File

@@ -4,15 +4,228 @@
#include "flutter/shell/platform/android/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 {
AndroidContextGLImpeller::AndroidContextGLImpeller()
: AndroidContext(AndroidRenderingAPI::kOpenGLES) {}
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<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);
FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker);
};
static std::shared_ptr<impeller::Context> CreateImpellerContext(
const std::shared_ptr<impeller::ReactorGLES::Worker>& worker) {
auto proc_table = std::make_unique<impeller::ProcTableGLES>(
impeller::egl::CreateProcAddressResolver());
if (!proc_table->IsValid()) {
FML_LOG(ERROR) << "Could not create OpenGL proc table.";
return nullptr;
}
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles_data,
impeller_entity_shaders_gles_length),
std::make_shared<fml::NonOwnedMapping>(
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(
std::unique_ptr<impeller::egl::Display> display)
: AndroidContext(AndroidRenderingAPI::kOpenGLES),
reactor_worker_(std::shared_ptr<ReactorWorker>(new ReactorWorker())),
display_(std::move(display)) {
if (!display_ || !display_->IsValid()) {
FML_DLOG(ERROR) << "Could not create context with invalid 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<impeller::egl::Config> 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";
}
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<impeller::egl::Surface>
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<impeller::egl::Surface>
AndroidContextGLImpeller::CreateOnscreenSurface(EGLNativeWindowType window) {
return display_->CreateWindowSurface(*onscreen_config_, window);
}
} // namespace flutter

View File

@@ -6,20 +6,40 @@
#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 {
class AndroidContextGLImpeller : public AndroidContext {
public:
AndroidContextGLImpeller();
explicit AndroidContextGLImpeller(
std::unique_ptr<impeller::egl::Display> display);
~AndroidContextGLImpeller();
// |AndroidContext|
bool IsValid() const override;
bool ResourceContextMakeCurrent(impeller::egl::Surface* offscreen_surface);
bool ResourceContextClearCurrent();
std::unique_ptr<impeller::egl::Surface> CreateOffscreenSurface();
bool OnscreenContextMakeCurrent(impeller::egl::Surface* onscreen_surface);
bool OnscreenContextClearCurrent();
std::unique_ptr<impeller::egl::Surface> CreateOnscreenSurface(
EGLNativeWindowType window);
private:
class ReactorWorker;
std::shared_ptr<ReactorWorker> reactor_worker_;
std::unique_ptr<impeller::egl::Display> display_;
std::unique_ptr<impeller::egl::Config> onscreen_config_;
std::unique_ptr<impeller::egl::Config> offscreen_config_;
std::unique_ptr<impeller::egl::Context> onscreen_context_;
std::unique_ptr<impeller::egl::Context> offscreen_context_;
bool is_valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextGLImpeller);
};

View File

@@ -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<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto jni = std::make_shared<JNIMock>();
TEST(AndroidContextGLImpeller, MSAAFirstAttempt) {
auto display = std::make_unique<MockDisplay>();
EXPECT_CALL(*display, IsValid).WillRepeatedly(Return(true));
auto first_result = std::make_unique<Config>(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<Config>())));
auto surface = std::make_unique<AndroidSurfaceGLImpeller>(context, jni,
std::move(display));
ASSERT_TRUE(surface);
auto context = std::make_unique<AndroidContextGLImpeller>(std::move(display));
ASSERT_TRUE(context);
}
TEST(AndroidSurfaceGLImpeller, FallbackForEmulator) {
auto context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto jni = std::make_shared<JNIMock>();
TEST(AndroidContextGLImpeller, FallbackForEmulator) {
auto display = std::make_unique<MockDisplay>();
EXPECT_CALL(*display, IsValid).WillRepeatedly(Return(true));
std::unique_ptr<Config> 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<Config>())));
auto surface = std::make_unique<AndroidSurfaceGLImpeller>(context, jni,
std::move(display));
ASSERT_TRUE(surface);
auto context = std::make_unique<AndroidContextGLImpeller>(std::move(display));
ASSERT_TRUE(context);
}
} // namespace testing
} // namespace flutter

View File

@@ -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,55 +13,6 @@ namespace flutter {
namespace testing {
namespace android {
namespace {
class MockPlatformViewAndroidJNI : public PlatformViewAndroidJNI {
public:
MOCK_METHOD2(FlutterViewHandlePlatformMessage,
void(std::unique_ptr<flutter::PlatformMessage> message,
int responseId));
MOCK_METHOD2(FlutterViewHandlePlatformMessageResponse,
void(int responseId, std::unique_ptr<fml::Mapping> data));
MOCK_METHOD3(FlutterViewUpdateSemantics,
void(std::vector<uint8_t> buffer,
std::vector<std::string> strings,
std::vector<std::vector<uint8_t>> string_attribute_args));
MOCK_METHOD2(FlutterViewUpdateCustomAccessibilityActions,
void(std::vector<uint8_t> actions_buffer,
std::vector<std::string> 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<PlatformViewAndroidJNI::OverlayMetadata>());
MOCK_METHOD0(FlutterViewDestroyOverlaySurfaces, void());
MOCK_METHOD1(FlutterViewComputePlatformResolvedLocale,
std::unique_ptr<std::vector<std::string>>(
std::vector<std::string> supported_locales_data));
MOCK_METHOD0(GetDisplayRefreshRate, double());
MOCK_METHOD0(GetDisplayWidth, double());
MOCK_METHOD0(GetDisplayHeight, double());
MOCK_METHOD0(GetDisplayDensity, double());
MOCK_METHOD1(RequestDartDeferredLibrary, bool(int loading_unit_id));
};
TaskRunners MakeTaskRunners(const std::string& thread_label,
const ThreadHost& thread_host) {
@@ -131,9 +81,8 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNotNull) {
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto android_context = std::make_shared<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
auto jni = std::make_shared<MockPlatformViewAndroidJNI>();
auto android_surface =
std::make_unique<AndroidSurfaceGLSkia>(android_context, jni);
std::make_unique<AndroidSurfaceGLSkia>(android_context);
auto window = fml::MakeRefCounted<AndroidNativeWindow>(
nullptr, /*is_fake_window=*/true);
android_surface->SetNativeWindow(window);
@@ -159,9 +108,8 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) {
TaskRunners task_runners = MakeTaskRunners(thread_label, thread_host);
auto android_context = std::make_shared<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, environment, task_runners, 0);
auto jni = std::make_shared<MockPlatformViewAndroidJNI>();
auto android_surface =
std::make_unique<AndroidSurfaceGLSkia>(android_context, jni);
std::make_unique<AndroidSurfaceGLSkia>(android_context);
EXPECT_EQ(android_surface->GetOnscreenSurface(), nullptr);
android_surface->CreateSnapshotSurface();
EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr);

View File

@@ -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<impeller::Context> CreateImpellerContext(
const fml::RefPtr<vulkan::VulkanProcTable>& proc_table,
const std::shared_ptr<fml::ConcurrentMessageLoop>& concurrent_loop,
bool enable_vulkan_validation) {
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
impeller_entity_shaders_vk_length),
std::make_shared<fml::NonOwnedMapping>(impeller_scene_shaders_vk_data,
impeller_scene_shaders_vk_length),
std::make_shared<fml::NonOwnedMapping>(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<vulkan::VulkanProcTable>()),
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

View File

@@ -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<vulkan::VulkanProcTable> proc_table_;
std::shared_ptr<fml::ConcurrentMessageLoop> workers_;
bool is_valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContextVulkanImpeller);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_VULKAN_IMPELLER_H_

View File

@@ -5,184 +5,21 @@
#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<std::thread::id, bool> reactions_allowed_ IPLR_GUARDED_BY(mutex_);
FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker);
};
static std::shared_ptr<impeller::Context> CreateImpellerContext(
const std::shared_ptr<impeller::ReactorGLES::Worker>& worker) {
auto proc_table = std::make_unique<impeller::ProcTableGLES>(
impeller::egl::CreateProcAddressResolver());
if (!proc_table->IsValid()) {
FML_LOG(ERROR) << "Could not create OpenGL proc table.";
return nullptr;
}
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles_data,
impeller_entity_shaders_gles_length),
std::make_shared<fml::NonOwnedMapping>(
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<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
std::unique_ptr<impeller::egl::Display> display)
: AndroidSurface(android_context),
reactor_worker_(std::shared_ptr<ReactorWorker>(new ReactorWorker())),
display_(std::move(display)) {
if (!display_->IsValid()) {
FML_DLOG(ERROR) << "Could not create surface with invalid Display.";
return;
}
const std::shared_ptr<AndroidContextGLImpeller>& android_context)
: android_context_(android_context) {
offscreen_surface_ = android_context_->CreateOffscreenSurface();
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<impeller::egl::Config> 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)) {
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);
// The onscreen surface will be acquired once the native window is set.
is_valid_ = true;
@@ -198,10 +35,10 @@ bool AndroidSurfaceGLImpeller::IsValid() const {
// |AndroidSurface|
std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateGPUSurface(
GrDirectContext* gr_context) {
auto surface =
std::make_unique<GPUSurfaceGLImpeller>(this, // delegate
impeller_context_ // context
);
auto surface = std::make_unique<GPUSurfaceGLImpeller>(
this, // delegate
android_context_->GetImpellerContext() // context
);
if (!surface->IsValid()) {
return nullptr;
}
@@ -223,20 +60,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 +86,7 @@ std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateSnapshotSurface() {
// |AndroidSurface|
std::shared_ptr<impeller::Context>
AndroidSurfaceGLImpeller::GetImpellerContext() {
return impeller_context_;
return android_context_->GetImpellerContext();
}
// |GPUSurfaceGLDelegate|
@@ -264,20 +96,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 +158,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;

View File

@@ -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,10 +17,8 @@ namespace flutter {
class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate,
public AndroidSurface {
public:
AndroidSurfaceGLImpeller(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
std::unique_ptr<impeller::egl::Display> display);
explicit AndroidSurfaceGLImpeller(
const std::shared_ptr<AndroidContextGLImpeller>& android_context);
// |AndroidSurface|
~AndroidSurfaceGLImpeller() override;
@@ -75,17 +73,9 @@ class AndroidSurfaceGLImpeller final : public GPUSurfaceGLDelegate,
sk_sp<const GrGLInterface> GetGLInterface() const override;
private:
class ReactorWorker;
std::shared_ptr<ReactorWorker> reactor_worker_;
std::unique_ptr<impeller::egl::Display> display_;
std::unique_ptr<impeller::egl::Config> onscreen_config_;
std::unique_ptr<impeller::egl::Config> offscreen_config_;
std::shared_ptr<AndroidContextGLImpeller> android_context_;
std::unique_ptr<impeller::egl::Surface> onscreen_surface_;
std::unique_ptr<impeller::egl::Surface> offscreen_surface_;
std::unique_ptr<impeller::egl::Context> onscreen_context_;
std::unique_ptr<impeller::egl::Context> offscreen_context_;
std::shared_ptr<impeller::Context> impeller_context_;
fml::RefPtr<AndroidNativeWindow> native_window_;
bool is_valid_ = false;

View File

@@ -21,14 +21,13 @@ constexpr char kEmulatorRendererPrefix[] =
} // anonymous namespace
AndroidSurfaceGLSkia::AndroidSurfaceGLSkia(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
: AndroidSurface(android_context),
const std::shared_ptr<AndroidContextGLSkia>& 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<Surface> AndroidSurfaceGLSkia::CreateGPUSurface(
@@ -55,10 +54,10 @@ std::unique_ptr<Surface> AndroidSurfaceGLSkia::CreateGPUSurface(
true);
} else {
sk_sp<GrDirectContext> 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<GPUSurfaceGLSkia>(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<GLContextResult> 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<const GrGLInterface> AndroidSurfaceGLSkia::GetGLInterface() const {
reinterpret_cast<const char*>(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<const GrGLInterface> AndroidSurfaceGLSkia::GetGLInterface() const {
return GPUSurfaceGLDelegate::GetGLInterface();
}
AndroidContextGLSkia* AndroidSurfaceGLSkia::GLContextPtr() const {
return reinterpret_cast<AndroidContextGLSkia*>(android_context_.get());
}
std::unique_ptr<Surface> AndroidSurfaceGLSkia::CreateSnapshotSurface() {
if (!onscreen_surface_ || !onscreen_surface_->IsValid()) {
onscreen_surface_ = GLContextPtr()->CreatePbufferSurface();
onscreen_surface_ = android_context_->CreatePbufferSurface();
}
sk_sp<GrDirectContext> 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<GPUSurfaceGLSkia>(main_skia_context, this, true);

View File

@@ -21,9 +21,8 @@ namespace flutter {
class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate,
public AndroidSurface {
public:
AndroidSurfaceGLSkia(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
explicit AndroidSurfaceGLSkia(
const std::shared_ptr<AndroidContextGLSkia>& android_context);
~AndroidSurfaceGLSkia() override;
@@ -82,16 +81,11 @@ class AndroidSurfaceGLSkia final : public GPUSurfaceGLDelegate,
}
private:
std::shared_ptr<AndroidContextGLSkia> android_context_;
fml::RefPtr<AndroidNativeWindow> native_window_;
std::unique_ptr<AndroidEGLSurface> onscreen_surface_;
std::unique_ptr<AndroidEGLSurface> 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);
};

View File

@@ -40,10 +40,7 @@ bool GetSkColorType(int32_t buffer_format,
} // anonymous namespace
AndroidSurfaceSoftware::AndroidSurfaceSoftware(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
: AndroidSurface(android_context) {
AndroidSurfaceSoftware::AndroidSurfaceSoftware() {
GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_,
&target_alpha_type_);
}

View File

@@ -19,9 +19,7 @@ namespace flutter {
class AndroidSurfaceSoftware final : public AndroidSurface,
public GPUSurfaceSoftwareDelegate {
public:
AndroidSurfaceSoftware(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
AndroidSurfaceSoftware();
~AndroidSurfaceSoftware() override;

View File

@@ -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<impeller::Context> CreateImpellerContext(
const fml::RefPtr<vulkan::VulkanProcTable>& proc_table,
const std::shared_ptr<fml::ConcurrentMessageLoop>& concurrent_loop,
bool enable_vulkan_validation) {
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
impeller_entity_shaders_vk_length),
std::make_shared<fml::NonOwnedMapping>(impeller_scene_shaders_vk_data,
impeller_scene_shaders_vk_length),
std::make_shared<fml::NonOwnedMapping>(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<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
bool enable_vulkan_validation)
: AndroidSurface(android_context),
proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>()),
workers_(fml::ConcurrentMessageLoop::Create()) {
impeller_context_ =
CreateImpellerContext(proc_table_, workers_, enable_vulkan_validation);
is_valid_ =
proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context_;
const std::shared_ptr<AndroidContextVulkanImpeller>& android_context)
: android_context_(android_context) {
is_valid_ = android_context_->IsValid();
}
AndroidSurfaceVulkanImpeller::~AndroidSurfaceVulkanImpeller() = default;
@@ -79,7 +43,8 @@ std::unique_ptr<Surface> AndroidSurfaceVulkanImpeller::CreateGPUSurface(
}
std::unique_ptr<GPUSurfaceVulkanImpeller> gpu_surface =
std::make_unique<GPUSurfaceVulkanImpeller>(impeller_context_);
std::make_unique<GPUSurfaceVulkanImpeller>(
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<impeller::Context>
AndroidSurfaceVulkanImpeller::GetImpellerContext() {
return impeller_context_;
return android_context_->GetImpellerContext();
}
} // namespace flutter

View File

@@ -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<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
bool enable_vulkan_validation);
explicit AndroidSurfaceVulkanImpeller(
const std::shared_ptr<AndroidContextVulkanImpeller>& android_context);
~AndroidSurfaceVulkanImpeller() override;
@@ -48,10 +46,8 @@ class AndroidSurfaceVulkanImpeller : public AndroidSurface {
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;
private:
fml::RefPtr<vulkan::VulkanProcTable> proc_table_;
std::shared_ptr<AndroidContextVulkanImpeller> android_context_;
fml::RefPtr<AndroidNativeWindow> native_window_;
std::shared_ptr<fml::ConcurrentMessageLoop> workers_;
std::shared_ptr<impeller::Context> impeller_context_;
bool is_valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceVulkanImpeller);

View File

@@ -15,6 +15,7 @@ source_set("context") {
deps = [
"//flutter/fml",
"//flutter/impeller/renderer",
"//third_party/skia",
]

View File

@@ -32,4 +32,13 @@ sk_sp<GrDirectContext> AndroidContext::GetMainSkiaContext() const {
return main_context_;
}
std::shared_ptr<impeller::Context> AndroidContext::GetImpellerContext() const {
return impeller_context_;
}
void AndroidContext::SetImpellerContext(
const std::shared_ptr<impeller::Context>& context) {
impeller_context_ = context;
}
} // namespace flutter

View File

@@ -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<GrDirectContext> GetMainSkiaContext() const;
//----------------------------------------------------------------------------
/// @brief Accessor for the Impeller context associated with
/// AndroidSurfaces and the raster thread.
///
std::shared_ptr<impeller::Context> 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<impeller::Context>& context);
private:
const AndroidRenderingAPI rendering_api_;
// This is the Skia context used for on-screen rendering.
sk_sp<GrDirectContext> main_context_;
std::shared_ptr<impeller::Context> impeller_context_;
FML_DISALLOW_COPY_AND_ASSIGN(AndroidContext);
};

View File

@@ -264,7 +264,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
auto frame_size = SkISize::Make(1000, 1000);
SurfaceFrame::FramebufferInfo framebuffer_info;
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size, framebuffer_info]() {
[gr_context, window, frame_size, framebuffer_info]() {
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size, framebuffer_info]() {
[gr_context, window, frame_size, framebuffer_info]() {
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size, framebuffer_info]() {
[gr_context, window, frame_size, framebuffer_info]() {
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size, framebuffer_info]() {
[gr_context, window, frame_size, framebuffer_info]() {
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size, framebuffer_info]() {
[gr_context, window, frame_size, framebuffer_info]() {
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size, framebuffer_info]() {
[gr_context, window, frame_size, framebuffer_info]() {
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window, frame_size]() {
[gr_context, window, frame_size]() {
SurfaceFrame::FramebufferInfo framebuffer_info;
auto surface_frame_1 = std::make_unique<SurfaceFrame>(
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<AndroidSurfaceMock>(android_context);
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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))));

View File

@@ -50,10 +50,9 @@ TEST(SurfacePool, GetLayerAllocateOneLayer) {
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
auto surface_factory =
std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
auto surface_factory =
std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<TestAndroidSurfaceFactory>(
[&android_context, gr_context_1, gr_context_2, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
[gr_context_1, gr_context_2, window]() {
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
// 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<PlatformViewAndroidJNI::OverlayMetadata>(
1, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
auto surface_factory =
std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
auto surface_factory =
std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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<AndroidNativeWindow>(nullptr);
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
auto surface_factory =
std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
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));

View File

@@ -31,37 +31,29 @@ namespace flutter {
AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl(
const std::shared_ptr<AndroidContext>& context,
std::shared_ptr<PlatformViewAndroidJNI> 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<AndroidSurface> AndroidSurfaceFactoryImpl::CreateSurface() {
switch (android_context_->RenderingApi()) {
case AndroidRenderingAPI::kSoftware:
return std::make_unique<AndroidSurfaceSoftware>(android_context_,
jni_facade_);
return std::make_unique<AndroidSurfaceSoftware>();
case AndroidRenderingAPI::kOpenGLES:
if (enable_impeller_) {
// TODO(kaushikiska@): Enable this after wiring a preference for Vulkan backend.
#if false
return std::make_unique<AndroidSurfaceVulkanImpeller>(
android_context_, jni_facade_, enable_vulkan_validation_);
#else
return std::make_unique<AndroidSurfaceGLImpeller>(
android_context_, jni_facade_,
std::make_unique<impeller::egl::Display>());
#endif
std::static_pointer_cast<AndroidContextGLImpeller>(
android_context_));
} else {
return std::make_unique<AndroidSurfaceGLSkia>(android_context_,
jni_facade_);
return std::make_unique<AndroidSurfaceGLSkia>(
std::static_pointer_cast<AndroidContextGLSkia>(android_context_));
}
case AndroidRenderingAPI::kVulkan:
FML_DCHECK(enable_impeller_);
return std::make_unique<AndroidSurfaceVulkanImpeller>(
std::static_pointer_cast<AndroidContextVulkanImpeller>(
android_context_));
default:
FML_DCHECK(false);
return nullptr;
@@ -72,12 +64,20 @@ static std::shared_ptr<flutter::AndroidContext> 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<AndroidContext>(AndroidRenderingAPI::kSoftware);
}
if (enable_impeller) {
return std::make_unique<AndroidContextGLImpeller>();
// TODO(kaushikiska@): Enable this after wiring a preference for Vulkan
// backend.
#if false
return std::make_unique<AndroidContextVulkanImpeller>(enable_vulkan_validation);
#else
return std::make_unique<AndroidContextGLImpeller>(
std::make_unique<impeller::egl::Display>());
#endif
}
return std::make_unique<AndroidContextGLSkia>(
AndroidRenderingAPI::kOpenGLES, //
@@ -101,7 +101,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,
@@ -117,10 +118,8 @@ PlatformViewAndroid::PlatformViewAndroid(
FML_CHECK(android_context_->IsValid())
<< "Could not create surface from invalid Android context.";
surface_factory_ = std::make_shared<AndroidSurfaceFactoryImpl>(
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())

View File

@@ -27,9 +27,7 @@ namespace flutter {
class AndroidSurfaceFactoryImpl : public AndroidSurfaceFactory {
public:
AndroidSurfaceFactoryImpl(const std::shared_ptr<AndroidContext>& context,
std::shared_ptr<PlatformViewAndroidJNI> 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<AndroidContext>& android_context_;
std::shared_ptr<PlatformViewAndroidJNI> jni_facade_;
const bool enable_impeller_;
const bool enable_vulkan_validation_;
};
class PlatformViewAndroid final : public PlatformView {

View File

@@ -7,11 +7,7 @@
namespace flutter {
AndroidSurface::AndroidSurface(
const std::shared_ptr<AndroidContext>& android_context) {
FML_DCHECK(android_context->IsValid());
android_context_ = android_context;
}
AndroidSurface::AndroidSurface() = default;
AndroidSurface::~AndroidSurface() = default;

View File

@@ -46,9 +46,7 @@ class AndroidSurface {
virtual std::shared_ptr<impeller::Context> GetImpellerContext();
protected:
explicit AndroidSurface(
const std::shared_ptr<AndroidContext>& android_context);
std::shared_ptr<AndroidContext> android_context_;
AndroidSurface();
};
class AndroidSurfaceFactory {

View File

@@ -6,10 +6,6 @@
namespace flutter {
AndroidSurfaceMock::AndroidSurfaceMock(
const std::shared_ptr<AndroidContext>& android_context)
: AndroidSurface(android_context) {}
std::unique_ptr<GLContextResult> AndroidSurfaceMock::GLContextMakeCurrent() {
return std::make_unique<GLContextDefaultResult>(/*static_result=*/true);
}

View File

@@ -18,9 +18,6 @@ namespace flutter {
class AndroidSurfaceMock final : public GPUSurfaceGLDelegate,
public AndroidSurface {
public:
explicit AndroidSurfaceMock(
const std::shared_ptr<AndroidContext>& android_context);
MOCK_METHOD(bool, IsValid, (), (const, override));
MOCK_METHOD(void, TeardownOnScreenContext, (), (override));