blob: b16179dde2bcf69a25112ff335144fb7a7cb0a99 [file] [log] [blame]
// 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/platform_view_android.h"
#include <android/api-level.h>
#include <memory>
#include <utility>
#include "flutter/common/graphics/texture.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/shell/common/shell_io_manager.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/android_context_gl_skia.h"
#include "flutter/shell/platform/android/android_context_vulkan_impeller.h"
#include "flutter/shell/platform/android/android_surface_gl_impeller.h"
#include "flutter/shell/platform/android/android_surface_gl_skia.h"
#include "flutter/shell/platform/android/android_surface_software.h"
#include "flutter/shell/platform/android/image_external_texture_gl.h"
#include "flutter/shell/platform/android/surface_texture_external_texture_gl.h"
#include "fml/logging.h"
#if IMPELLER_ENABLE_VULKAN // b/258506856 for why this is behind an if
#include "flutter/shell/platform/android/android_surface_vulkan_impeller.h"
#include "flutter/shell/platform/android/image_external_texture_vk.h"
#endif
#include "flutter/shell/platform/android/context/android_context.h"
#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "flutter/shell/platform/android/platform_message_response_android.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
#include "flutter/shell/platform/android/surface/snapshot_surface_producer.h"
#include "flutter/shell/platform/android/vsync_waiter_android.h"
namespace flutter {
AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl(
const std::shared_ptr<AndroidContext>& context,
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>();
case AndroidRenderingAPI::kImpellerOpenGLES:
return std::make_unique<AndroidSurfaceGLImpeller>(
std::static_pointer_cast<AndroidContextGLImpeller>(android_context_));
case AndroidRenderingAPI::kSkiaOpenGLES:
return std::make_unique<AndroidSurfaceGLSkia>(
std::static_pointer_cast<AndroidContextGLSkia>(android_context_));
case AndroidRenderingAPI::kImpellerVulkan:
return std::make_unique<AndroidSurfaceVulkanImpeller>(
std::static_pointer_cast<AndroidContextVulkanImpeller>(
android_context_));
}
FML_UNREACHABLE();
}
static std::shared_ptr<flutter::AndroidContext> CreateAndroidContext(
bool use_software_rendering,
const flutter::TaskRunners& task_runners,
AndroidRenderingAPI android_rendering_api,
bool enable_vulkan_validation,
bool enable_opengl_gpu_tracing,
bool enable_vulkan_gpu_tracing) {
switch (android_rendering_api) {
case AndroidRenderingAPI::kSoftware:
return std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
case AndroidRenderingAPI::kImpellerOpenGLES:
return std::make_unique<AndroidContextGLImpeller>(
std::make_unique<impeller::egl::Display>(),
enable_opengl_gpu_tracing);
case AndroidRenderingAPI::kImpellerVulkan:
return std::make_unique<AndroidContextVulkanImpeller>(
enable_vulkan_validation, enable_vulkan_gpu_tracing);
case AndroidRenderingAPI::kSkiaOpenGLES:
return std::make_unique<AndroidContextGLSkia>(
fml::MakeRefCounted<AndroidEnvironmentGL>(), //
task_runners //
);
}
FML_UNREACHABLE();
}
PlatformViewAndroid::PlatformViewAndroid(
PlatformView::Delegate& delegate,
const flutter::TaskRunners& task_runners,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
bool use_software_rendering)
: PlatformViewAndroid(
delegate,
task_runners,
jni_facade,
CreateAndroidContext(
use_software_rendering,
task_runners,
delegate.OnPlatformViewGetSettings().android_rendering_api,
delegate.OnPlatformViewGetSettings().enable_vulkan_validation,
delegate.OnPlatformViewGetSettings().enable_opengl_gpu_tracing,
delegate.OnPlatformViewGetSettings().enable_vulkan_gpu_tracing)) {
}
PlatformViewAndroid::PlatformViewAndroid(
PlatformView::Delegate& delegate,
const flutter::TaskRunners& task_runners,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
const std::shared_ptr<flutter::AndroidContext>& android_context)
: PlatformView(delegate, task_runners),
jni_facade_(jni_facade),
android_context_(android_context),
platform_view_android_delegate_(jni_facade),
platform_message_handler_(new PlatformMessageHandlerAndroid(jni_facade)) {
if (android_context_) {
FML_CHECK(android_context_->IsValid())
<< "Could not create surface from invalid Android context.";
surface_factory_ = std::make_shared<AndroidSurfaceFactoryImpl>(
android_context_, //
delegate.OnPlatformViewGetSettings().enable_impeller //
);
android_surface_ = surface_factory_->CreateSurface();
FML_CHECK(android_surface_ && android_surface_->IsValid())
<< "Could not create an OpenGL, Vulkan or Software surface to set up "
"rendering.";
}
}
PlatformViewAndroid::~PlatformViewAndroid() = default;
void PlatformViewAndroid::NotifyCreated(
fml::RefPtr<AndroidNativeWindow> native_window) {
if (android_surface_) {
InstallFirstFrameCallback();
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetRasterTaskRunner(),
[&latch, surface = android_surface_.get(),
native_window = std::move(native_window)]() {
surface->SetNativeWindow(native_window);
latch.Signal();
});
latch.Wait();
}
PlatformView::NotifyCreated();
}
void PlatformViewAndroid::NotifySurfaceWindowChanged(
fml::RefPtr<AndroidNativeWindow> native_window) {
if (android_surface_) {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetRasterTaskRunner(),
[&latch, surface = android_surface_.get(),
native_window = std::move(native_window)]() {
surface->TeardownOnScreenContext();
surface->SetNativeWindow(native_window);
latch.Signal();
});
latch.Wait();
}
PlatformView::ScheduleFrame();
}
void PlatformViewAndroid::NotifyDestroyed() {
PlatformView::NotifyDestroyed();
if (android_surface_) {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetRasterTaskRunner(),
[&latch, surface = android_surface_.get()]() {
surface->TeardownOnScreenContext();
latch.Signal();
});
latch.Wait();
}
}
void PlatformViewAndroid::NotifyChanged(const SkISize& size) {
if (!android_surface_) {
return;
}
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetRasterTaskRunner(), //
[&latch, surface = android_surface_.get(), size]() {
surface->OnScreenSurfaceResize(size);
latch.Signal();
});
latch.Wait();
}
void PlatformViewAndroid::DispatchPlatformMessage(JNIEnv* env,
std::string name,
jobject java_message_data,
jint java_message_position,
jint response_id) {
uint8_t* message_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_message_data));
fml::MallocMapping message =
fml::MallocMapping::Copy(message_data, java_message_position);
fml::RefPtr<flutter::PlatformMessageResponse> response;
if (response_id) {
response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
response_id, jni_facade_, task_runners_.GetPlatformTaskRunner());
}
PlatformView::DispatchPlatformMessage(
std::make_unique<flutter::PlatformMessage>(
std::move(name), std::move(message), std::move(response)));
}
void PlatformViewAndroid::DispatchEmptyPlatformMessage(JNIEnv* env,
std::string name,
jint response_id) {
fml::RefPtr<flutter::PlatformMessageResponse> response;
if (response_id) {
response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
response_id, jni_facade_, task_runners_.GetPlatformTaskRunner());
}
PlatformView::DispatchPlatformMessage(
std::make_unique<flutter::PlatformMessage>(std::move(name),
std::move(response)));
}
// |PlatformView|
void PlatformViewAndroid::HandlePlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message) {
// Called from the ui thread.
platform_message_handler_->HandlePlatformMessage(std::move(message));
}
// |PlatformView|
void PlatformViewAndroid::OnPreEngineRestart() const {
jni_facade_->FlutterViewOnPreEngineRestart();
}
void PlatformViewAndroid::DispatchSemanticsAction(JNIEnv* env,
jint id,
jint action,
jobject args,
jint args_position) {
if (env->IsSameObject(args, NULL)) {
PlatformView::DispatchSemanticsAction(
id, static_cast<flutter::SemanticsAction>(action),
fml::MallocMapping());
return;
}
uint8_t* args_data = static_cast<uint8_t*>(env->GetDirectBufferAddress(args));
auto args_vector = fml::MallocMapping::Copy(args_data, args_position);
PlatformView::DispatchSemanticsAction(
id, static_cast<flutter::SemanticsAction>(action),
std::move(args_vector));
}
// |PlatformView|
void PlatformViewAndroid::UpdateSemantics(
flutter::SemanticsNodeUpdates update,
flutter::CustomAccessibilityActionUpdates actions) {
platform_view_android_delegate_.UpdateSemantics(update, actions);
}
void PlatformViewAndroid::RegisterExternalTexture(
int64_t texture_id,
const fml::jni::ScopedJavaGlobalRef<jobject>& surface_texture) {
switch (android_context_->RenderingApi()) {
case AndroidRenderingAPI::kImpellerOpenGLES:
// Impeller GLES.
RegisterTexture(std::make_shared<SurfaceTextureExternalTextureImpellerGL>(
std::static_pointer_cast<impeller::ContextGLES>(
android_context_->GetImpellerContext()),
texture_id, surface_texture, jni_facade_));
break;
case AndroidRenderingAPI::kSkiaOpenGLES:
// Legacy GL.
RegisterTexture(std::make_shared<SurfaceTextureExternalTextureGL>(
texture_id, surface_texture, jni_facade_));
break;
case AndroidRenderingAPI::kSoftware:
FML_LOG(INFO) << "Software rendering does not support external textures.";
break;
case AndroidRenderingAPI::kImpellerVulkan:
FML_LOG(ERROR) << "Impeller requires migrating plugins that create and "
"register surface textures to the new surface producer "
"API. See "
"https://docs.flutter.dev/release/breaking-changes/"
"android-surface-plugins";
}
}
void PlatformViewAndroid::RegisterImageTexture(
int64_t texture_id,
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry) {
switch (android_context_->RenderingApi()) {
case AndroidRenderingAPI::kImpellerOpenGLES:
// Impeller GLES.
RegisterTexture(std::make_shared<ImageExternalTextureGLImpeller>(
std::static_pointer_cast<impeller::ContextGLES>(
android_context_->GetImpellerContext()),
texture_id, image_texture_entry, jni_facade_));
break;
case AndroidRenderingAPI::kSkiaOpenGLES:
// Legacy GL.
RegisterTexture(std::make_shared<ImageExternalTextureGLSkia>(
std::static_pointer_cast<AndroidContextGLSkia>(android_context_),
texture_id, image_texture_entry, jni_facade_));
break;
case AndroidRenderingAPI::kImpellerVulkan:
RegisterTexture(std::make_shared<ImageExternalTextureVK>(
std::static_pointer_cast<impeller::ContextVK>(
android_context_->GetImpellerContext()),
texture_id, image_texture_entry, jni_facade_));
break;
case AndroidRenderingAPI::kSoftware:
FML_LOG(INFO) << "Software rendering does not support external textures.";
break;
}
}
// |PlatformView|
std::unique_ptr<VsyncWaiter> PlatformViewAndroid::CreateVSyncWaiter() {
return std::make_unique<VsyncWaiterAndroid>(task_runners_);
}
// |PlatformView|
std::unique_ptr<Surface> PlatformViewAndroid::CreateRenderingSurface() {
if (!android_surface_) {
return nullptr;
}
return android_surface_->CreateGPUSurface(
android_context_->GetMainSkiaContext().get());
}
// |PlatformView|
std::shared_ptr<ExternalViewEmbedder>
PlatformViewAndroid::CreateExternalViewEmbedder() {
return std::make_shared<AndroidExternalViewEmbedder>(
*android_context_, jni_facade_, surface_factory_, task_runners_);
}
// |PlatformView|
std::unique_ptr<SnapshotSurfaceProducer>
PlatformViewAndroid::CreateSnapshotSurfaceProducer() {
if (!android_surface_) {
return nullptr;
}
return std::make_unique<AndroidSnapshotSurfaceProducer>(*android_surface_);
}
// |PlatformView|
sk_sp<GrDirectContext> PlatformViewAndroid::CreateResourceContext() const {
if (!android_surface_) {
return nullptr;
}
sk_sp<GrDirectContext> resource_context;
if (android_surface_->ResourceContextMakeCurrent()) {
// TODO(chinmaygarde): Currently, this code depends on the fact that only
// the OpenGL surface will be able to make a resource context current. If
// this changes, this assumption breaks. Handle the same.
resource_context = ShellIOManager::CreateCompatibleResourceLoadingContext(
GrBackendApi::kOpenGL,
GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface());
} else {
FML_DLOG(ERROR) << "Could not make the resource context current.";
}
return resource_context;
}
// |PlatformView|
void PlatformViewAndroid::ReleaseResourceContext() const {
if (android_surface_) {
android_surface_->ResourceContextClearCurrent();
}
}
// |PlatformView|
std::shared_ptr<impeller::Context> PlatformViewAndroid::GetImpellerContext()
const {
if (android_surface_) {
return android_surface_->GetImpellerContext();
}
return nullptr;
}
// |PlatformView|
std::unique_ptr<std::vector<std::string>>
PlatformViewAndroid::ComputePlatformResolvedLocales(
const std::vector<std::string>& supported_locale_data) {
return jni_facade_->FlutterViewComputePlatformResolvedLocale(
supported_locale_data);
}
// |PlatformView|
void PlatformViewAndroid::RequestDartDeferredLibrary(intptr_t loading_unit_id) {
if (jni_facade_->RequestDartDeferredLibrary(loading_unit_id)) {
return;
}
return; // TODO(garyq): Call LoadDartDeferredLibraryFailure()
}
// |PlatformView|
void PlatformViewAndroid::LoadDartDeferredLibrary(
intptr_t loading_unit_id,
std::unique_ptr<const fml::Mapping> snapshot_data,
std::unique_ptr<const fml::Mapping> snapshot_instructions) {
delegate_.LoadDartDeferredLibrary(loading_unit_id, std::move(snapshot_data),
std::move(snapshot_instructions));
}
// |PlatformView|
void PlatformViewAndroid::LoadDartDeferredLibraryError(
intptr_t loading_unit_id,
const std::string error_message,
bool transient) {
delegate_.LoadDartDeferredLibraryError(loading_unit_id, error_message,
transient);
}
// |PlatformView|
void PlatformViewAndroid::UpdateAssetResolverByType(
std::unique_ptr<AssetResolver> updated_asset_resolver,
AssetResolver::AssetResolverType type) {
delegate_.UpdateAssetResolverByType(std::move(updated_asset_resolver), type);
}
void PlatformViewAndroid::InstallFirstFrameCallback() {
// On Platform Task Runner.
SetNextFrameCallback(
[platform_view = GetWeakPtr(),
platform_task_runner = task_runners_.GetPlatformTaskRunner()]() {
// On GPU Task Runner.
platform_task_runner->PostTask([platform_view]() {
// Back on Platform Task Runner.
if (platform_view) {
reinterpret_cast<PlatformViewAndroid*>(platform_view.get())
->FireFirstFrameCallback();
}
});
});
}
void PlatformViewAndroid::FireFirstFrameCallback() {
jni_facade_->FlutterViewOnFirstFrame();
}
double PlatformViewAndroid::GetScaledFontSize(double unscaled_font_size,
int configuration_id) const {
return jni_facade_->FlutterViewGetScaledFontSize(unscaled_font_size,
configuration_id);
}
} // namespace flutter