-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: tech-debtTechnical debt, code quality, testing, etc.Technical debt, code quality, testing, etc.engineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.platform-androidAndroid applications specificallyAndroid applications specificallyteam-androidOwned by Android platform teamOwned by Android platform teamtriaged-androidTriaged by Android platform teamTriaged by Android platform team
Description
It would be nice for our rendering selection logic for the Android embedder to be better tested/testable:
flutter/engine/src/flutter/shell/platform/android/flutter_main.cc
Lines 271 to 333 in e673061
| AndroidRenderingAPI FlutterMain::SelectedRenderingAPI( | |
| const flutter::Settings& settings) { | |
| if (settings.enable_software_rendering) { | |
| FML_CHECK(!settings.enable_impeller) | |
| << "Impeller does not support software rendering. Either disable " | |
| "software rendering or disable impeller."; | |
| return AndroidRenderingAPI::kSoftware; | |
| } | |
| constexpr AndroidRenderingAPI kVulkanUnsupportedFallback = | |
| AndroidRenderingAPI::kImpellerOpenGLES; | |
| // Debug/Profile only functionality for testing a specific | |
| // backend configuration. | |
| #ifndef FLUTTER_RELEASE | |
| if (settings.requested_rendering_backend == "opengles" && | |
| settings.enable_impeller) { | |
| return AndroidRenderingAPI::kImpellerOpenGLES; | |
| } | |
| if (settings.requested_rendering_backend == "vulkan" && | |
| settings.enable_impeller) { | |
| return AndroidRenderingAPI::kImpellerVulkan; | |
| } | |
| #endif | |
| if (settings.enable_impeller) { | |
| // Vulkan must only be used on API level 29+, as older API levels do not | |
| // have requisite features to support platform views. | |
| // | |
| // Even if this check returns true, Impeller may determine it cannot use | |
| // Vulkan for some other reason, such as a missing required extension or | |
| // feature. | |
| int api_level = android_get_device_api_level(); | |
| if (api_level < kMinimumAndroidApiLevelForVulkan) { | |
| return kVulkanUnsupportedFallback; | |
| } | |
| char product_model[PROP_VALUE_MAX]; | |
| __system_property_get("ro.product.model", product_model); | |
| if (IsDeviceEmulator(product_model)) { | |
| // Avoid using Vulkan on known emulators. | |
| return kVulkanUnsupportedFallback; | |
| } | |
| __system_property_get("ro.product.board", product_model); | |
| if (IsKnownBadSOC(product_model)) { | |
| // Avoid using Vulkan on known bad SoCs. | |
| return kVulkanUnsupportedFallback; | |
| } | |
| // Determine if Vulkan is supported by creating a Vulkan context and | |
| // checking if it is valid. | |
| impeller::ScopedValidationDisable disable_validation; | |
| auto vulkan_backend = std::make_unique<AndroidContextVKImpeller>( | |
| AndroidContext::ContextSettings{.enable_validation = false, | |
| .enable_gpu_tracing = false, | |
| .quiet = true}); | |
| if (!vulkan_backend->IsValid()) { | |
| return kVulkanUnsupportedFallback; | |
| } | |
| return AndroidRenderingAPI::kImpellerVulkan; | |
| } | |
| return AndroidRenderingAPI::kSkiaOpenGLES; | |
| } |
A few possible changes:
- Add a
AndroidRenderingAPI,AndroidDeviceStateandAndroidRenderingSelectortypes - Add tests for the different case
- Refactor the surrounding code to use this code only
I ran into wanting this in #163561.
A snippet as a starting place:
// 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_RENDERING_SELECTOR_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_RENDERING_SELECTOR_H_
#include <string>
namespace flutter {
/**
* @brief A combination of targeted graphics API and Impeller support for
* Android.
*/
enum class AndroidRenderingAPI {
/**
* @brief Software rendering backend for Skia.
*
* This rendering API is deprecated, and there is no replacement for Impeller.
* @deprecated
*/
kSkiaSoftware [[deprecated]],
/**
* @brief OpenGLES rendering backend for Skia.
*
* This rendering API is deprecated; an Impeller-based backend is used by
* default unless opted-out manually (either using `flutter run
* --no-enable-impeller` or `AndroidManifest.xml`).
*
* @see https://docs.flutter.dev/perf/impeller#android
* @deprecated
*/
kSkiaOpenGLES [[deprecated]],
/**
* @brief Vulkan rendering backend for Impeller.
*
* This API should be used if:
* - The current Android API level is at least 29+;
* - Not running on a known emulator (there are performance problems);
* - Not running on a known bad SoC (Vulkan is not working or working
* properly);
* - A Vulkan context can be successfully created.
*
* Or, if the requested rendering backend is explicitly Vulkan (a debug
* and profile-mode only feature for testing and debugging) by editing
* `AndroidManifest.xml`:
* `<meta-data android:name="io.flutter.embedding.android.ImpellerBackend"
* android:value="vulkan />`
*/
kImpellerVulkan,
/**
* @brief OpenGLES rendering backend for Impeller.
*
* This API is used as a fallback when `kImpellerVulkan` cannot be used or if
* the requested rendering backend is explicitly OpenGLES (a debug and
* profile-mode only feature for testing and debugging) by editing
* `AndroidManifest.xml`:
* `<meta-data android:name="io.flutter.embedding.android.ImpellerBackend"
* android:value="opengles />`
*/
kImpellerOpenGLES,
};
/**
* @brief Used by `AndroidRenderingAPI` to determine an appropriate rendering
* API.
*
* There are two ways to use this struct:
* 1. Create it with user-defined state (i.e., for testing or to adapt another
* source).
* 2. Use `fromNdk`, to extract the current state from the current Android
* device's NDK.
*/
struct AndroidDeviceState {
/**
* @brief The API level of the Android device.
*/
int apiLevel;
/**
* @brief The product model of the Android device.
*/
std::string_view productModel;
/**
* @brief The System on a Chip (SOC) board of the Android device.
*/
std::string_view productSocBoard;
/**
* @brief Extracts the Android device state from the NDK.
*
* @return An initialized AndroidDeviceState struct.
*/
static AndroidDeviceState fromNdk();
};
/**
* @brief Determines which `AndroidRenderingAPI` to use, based on a variety of
* factors.
*/
class AndroidRenderingSelector {
public:
~AndroidRenderingSelector();
AndroidRenderingAPI select(AndroidDeviceState options);
private:
AndroidRenderingSelector(const AndroidRenderingSelector&) = delete;
AndroidRenderingSelector& operator=(const AndroidRenderingSelector&) = delete;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_RENDERING_SELECTOR_H_Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: tech-debtTechnical debt, code quality, testing, etc.Technical debt, code quality, testing, etc.engineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.platform-androidAndroid applications specificallyAndroid applications specificallyteam-androidOwned by Android platform teamOwned by Android platform teamtriaged-androidTriaged by Android platform teamTriaged by Android platform team