Flutter Engine
 
Loading...
Searching...
No Matches
android_context_dynamic_impeller.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <android/api-level.h>
8#include <sys/system_properties.h>
9#include <memory>
10
13
14namespace fs = std::filesystem;
15
16namespace flutter {
17
18namespace {
19
20static const constexpr char* kAndroidHuawei = "android-huawei";
21
22static constexpr const char* kBadSocs[] = {
23 // Most Exynos Series SoC. These are SoCs that crash when using AHB imports.
24 "exynos7870", //
25 "exynos7880", //
26 "exynos7872", //
27 "exynos7884", //
28 "exynos7885", //
29 "exynos7904", //
30 // Mongoose line.
31 "exynos8890", //
32 "exynos8895", //
33 "exynos9609", //
34 "exynos9610", //
35 "exynos9611", //
36 "exynos9810", //
37 // `exynos9820` and `exynos9825` have graphical errors:
38 // https://github.com/flutter/flutter/issues/171992.
39 "exynos9820", //
40 "exynos9825" //
41};
42
43static bool IsDeviceEmulator() {
44 char property[PROP_VALUE_MAX];
45
46 __system_property_get("ro.hardware", property);
47 std::string_view hardware_prop(property);
48 if (hardware_prop == "goldfish" || hardware_prop == "ranchu" ||
49 hardware_prop == "qemu") {
50 return true;
51 }
52
53 __system_property_get("ro.product.model", property);
54 std::string_view model_prop(property);
55 if (model_prop.find("gphone") != std::string::npos) {
56 return true;
57 }
58
59 if (::access("/dev/qemu_pipe", F_OK) == 0) {
60 return true;
61 }
62
63 return false;
64}
65
66static bool IsKnownBadSOC(std::string_view hardware) {
67 // TODO(jonahwilliams): if the list gets too long (> 16), convert
68 // to a hash map first.
69 for (const auto& board : kBadSocs) {
70 if (strcmp(board, hardware.data()) == 0) {
71 return true;
72 }
73 }
74 return false;
75}
76
77static std::shared_ptr<AndroidContextVKImpeller>
78GetActualRenderingAPIForImpeller(
79 int api_level,
80 const AndroidContext::ContextSettings& settings) {
81 constexpr int kMinimumAndroidApiLevelForMediaTekVulkan = 31;
82
83 // have requisite features to support platform views.
84 //
85 // Even if this check returns true, Impeller may determine it cannot use
86 // Vulkan for some other reason, such as a missing required extension or
87 // feature. In these cases it will use OpenGLES.
88 if (IsDeviceEmulator()) {
89 // Avoid using Vulkan on known emulators.
90 return nullptr;
91 }
92
93 char property[PROP_VALUE_MAX];
94 __system_property_get("ro.com.google.clientidbase", property);
95 if (strcmp(property, kAndroidHuawei) == 0) {
96 // Avoid using Vulkan on Huawei as AHB imports do not
97 // consistently work.
98 return nullptr;
99 }
100
101 if (api_level < kMinimumAndroidApiLevelForMediaTekVulkan &&
102 __system_property_find("ro.vendor.mediatek.platform") != nullptr) {
103 // Probably MediaTek. Avoid Vulkan if older than 34 to work around
104 // crashes when importing AHB.
105 return nullptr;
106 }
107
108 __system_property_get("ro.product.board", property);
109 if (IsKnownBadSOC(property)) {
110 FML_LOG(INFO)
111 << "Known bad Vulkan driver encountered, falling back to OpenGLES.";
112 return nullptr;
113 }
114
115 // Determine if Vulkan is supported by creating a Vulkan context and
116 // checking if it is valid.
117 impeller::ScopedValidationDisable disable_validation;
118 auto vulkan_backend = std::make_shared<AndroidContextVKImpeller>(
119 AndroidContext::ContextSettings{
120#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
121 .enable_validation = settings.enable_validation,
122#else
123 .enable_validation = false,
124#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
125 .enable_gpu_tracing = settings.enable_gpu_tracing,
126 .enable_surface_control = settings.enable_surface_control,
127 .impeller_flags =
128 {
129 .lazy_shader_mode = settings.impeller_flags.lazy_shader_mode,
130 .antialiased_lines =
131 settings.impeller_flags.antialiased_lines,
132 },
133 });
134 if (!vulkan_backend->IsValid()) {
135 return nullptr;
136 }
137 return vulkan_backend;
138}
139} // namespace
140
145
147
157
158std::shared_ptr<impeller::Context>
160 if (vk_context_) {
161 return vk_context_->GetImpellerContext();
162 }
163 if (gl_context_) {
164 return gl_context_->GetImpellerContext();
165 }
166 return nullptr;
167}
168
169std::shared_ptr<AndroidContextGLImpeller>
171 return gl_context_;
172}
173
174std::shared_ptr<AndroidContextVKImpeller>
176 return vk_context_;
177}
178
180 if (vk_context_ || gl_context_) {
181 return;
182 }
183 vk_context_ = GetActualRenderingAPIForImpeller(android_get_device_api_level(),
184 settings_);
185 if (!vk_context_) {
186 gl_context_ = std::make_shared<AndroidContextGLImpeller>(
187 std::make_unique<impeller::egl::Display>(),
188 settings_.enable_gpu_tracing);
189 }
190}
191
192} // namespace flutter
void SetupImpellerContext() override
Perform deferred setup for the impeller Context.
AndroidContextDynamicImpeller(const AndroidContext::ContextSettings &settings)
std::shared_ptr< AndroidContextVKImpeller > GetVKContext() const
Retrieve the VK context if it was created, or nullptr.
std::shared_ptr< AndroidContextGLImpeller > GetGLContext() const
Retrieve the GL Context if it was created, or nullptr.
std::shared_ptr< impeller::Context > GetImpellerContext() const override
Accessor for the Impeller context associated with AndroidSurfaces and the raster thread.
Holds state that is shared across Android surfaces.
Settings settings_
#define FML_LOG(severity)
Definition logging.h:101