blob: 3823a89ee2a46374bd257c5aeb049deeee29562a [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/gl_features.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/strings/string_split.h"
#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "ui/gl/gl_switches.h"
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/android_info.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "ui/gfx/android/achoreographer_compat.h"
#include "ui/gfx/android/android_surface_control_compat.h"
#endif
namespace features {
namespace {
#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByBrand{
&kDefaultPassthroughCommandDecoder, "BlockListByBrand", ""};
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByDevice{
&kDefaultPassthroughCommandDecoder, "BlockListByDevice", ""};
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByAndroidBuildId{
&kDefaultPassthroughCommandDecoder, "BlockListByAndroidBuildId", ""};
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByManufacturer{
&kDefaultPassthroughCommandDecoder, "BlockListByManufacturer", ""};
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByModel{
&kDefaultPassthroughCommandDecoder, "BlockListByModel", ""};
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByBoard{
&kDefaultPassthroughCommandDecoder, "BlockListByBoard", ""};
const base::FeatureParam<std::string>
kPassthroughCommandDecoderBlockListByAndroidBuildFP{
&kDefaultPassthroughCommandDecoder, "BlockListByAndroidBuildFP", ""};
bool IsDeviceBlocked(const std::string& field, const std::string& block_list) {
auto disable_patterns = base::SplitString(
block_list, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
for (const auto& disable_pattern : disable_patterns) {
if (base::MatchPattern(field, disable_pattern))
return true;
}
return false;
}
#endif
BASE_FEATURE(kForceANGLEFeatures, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kForcedANGLEEnabledFeaturesFP{
&kForceANGLEFeatures, "EnabledFeatures", ""};
const base::FeatureParam<std::string> kForcedANGLEDisabledFeaturesFP{
&kForceANGLEFeatures, "DisabledFeatures", ""};
void SplitAndAppendANGLEFeatureList(const std::string& list,
std::vector<std::string>& out_features) {
for (std::string& feature_name : base::SplitString(
list, ", ;", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
out_features.push_back(std::move(feature_name));
}
}
} // namespace
#if BUILDFLAG(IS_APPLE)
BASE_FEATURE(kGpuVsync, base::FEATURE_DISABLED_BY_DEFAULT);
#else
BASE_FEATURE(kGpuVsync, base::FEATURE_ENABLED_BY_DEFAULT);
#endif
#if BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
// Use the passthrough command decoder by default. This can be overridden with
// the --use-cmd-decoder=passthrough or --use-cmd-decoder=validating flags.
// Feature lives in ui/gl because it affects the GL binding initialization on
// platforms that would otherwise not default to using EGL bindings.
BASE_FEATURE(kDefaultPassthroughCommandDecoder,
base::FEATURE_DISABLED_BY_DEFAULT);
// Add a small delay in shader compiling if validating command decoder is used.
// This is to verify if passthrough command decoder impacting negatively top
// level metrics could be due to slower shader compiling.
BASE_FEATURE(kAddDelayToGLCompileShader, base::FEATURE_DISABLED_BY_DEFAULT);
// Histogram |GrCompileShaderUs| mean is 1.8ms (native) vs 3.1ms (ANGLE).
// Therefore, we add a 1.3ms delay to shader compiling.
constexpr base::FeatureParam<base::TimeDelta> kGLCompileShaderDelay = {
&kAddDelayToGLCompileShader, /*name=*/"interval",
/*default_value=*/base::Microseconds(1300)};
#endif // !defined(PASSTHROUGH_COMMAND_DECODER_LAUNCHED)
#if BUILDFLAG(IS_WIN)
// If true, VsyncThreadWin will use the compositor clock
// to determine the vsync interval.
BASE_FEATURE(kUseCompositorClockVSyncInterval,
base::FEATURE_DISABLED_BY_DEFAULT);
bool UseCompositorClockVSyncInterval() {
return base::win::GetVersion() >= base::win::Version::WIN11_24H2 &&
base::FeatureList::IsEnabled(
features::kUseCompositorClockVSyncInterval);
}
#endif // BUILDFLAG(IS_WIN)
bool UseGpuVsync() {
return !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuVsync) &&
base::FeatureList::IsEnabled(features::kGpuVsync);
}
bool IsAndroidFrameDeadlineEnabled() {
#if BUILDFLAG(IS_ANDROID)
static bool enabled = base::android::android_info::sdk_int() >=
base::android::android_info::SDK_VERSION_T &&
gfx::AChoreographerCompat33::Get().supported &&
gfx::SurfaceControl::SupportsSetFrameTimeline() &&
gfx::SurfaceControl::SupportsSetEnableBackPressure();
return enabled;
#else
return false;
#endif
}
bool UsePassthroughCommandDecoder() {
#if !BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
return true;
#else
if (!base::FeatureList::IsEnabled(kDefaultPassthroughCommandDecoder))
return false;
#if BUILDFLAG(IS_ANDROID)
// Check block list against build info.
if (IsDeviceBlocked(base::android::android_info::brand(),
kPassthroughCommandDecoderBlockListByBrand.Get())) {
return false;
}
if (IsDeviceBlocked(base::android::android_info::device(),
kPassthroughCommandDecoderBlockListByDevice.Get())) {
return false;
}
if (IsDeviceBlocked(
base::android::android_info::android_build_id(),
kPassthroughCommandDecoderBlockListByAndroidBuildId.Get())) {
return false;
}
if (IsDeviceBlocked(
base::android::android_info::manufacturer(),
kPassthroughCommandDecoderBlockListByManufacturer.Get())) {
return false;
}
if (IsDeviceBlocked(base::android::android_info::model(),
kPassthroughCommandDecoderBlockListByModel.Get())) {
return false;
}
if (IsDeviceBlocked(base::android::android_info::board(),
kPassthroughCommandDecoderBlockListByBoard.Get())) {
return false;
}
if (IsDeviceBlocked(
base::android::android_info::android_build_fp(),
kPassthroughCommandDecoderBlockListByAndroidBuildFP.Get())) {
return false;
}
#endif // BUILDFLAG(IS_ANDROID)
return true;
#endif // defined(PASSTHROUGH_COMMAND_DECODER_LAUNCHED)
}
#if DCHECK_IS_ON()
bool IsANGLEValidationEnabled() {
return true;
}
#else
// Enables the use of ANGLE validation for EGL and GL (non-WebGL) contexts.
BASE_FEATURE(kDefaultEnableANGLEValidation, base::FEATURE_DISABLED_BY_DEFAULT);
bool IsANGLEValidationEnabled() {
return base::FeatureList::IsEnabled(kDefaultEnableANGLEValidation) &&
UsePassthroughCommandDecoder();
}
#endif
// Killswitch feature for allowing ANGLE to pass untranslated shaders to the
// driver.
BASE_FEATURE(kAllowANGLEPassthroughShaders, base::FEATURE_ENABLED_BY_DEFAULT);
bool IsANGLEPassthroughShadersAllowed() {
return base::FeatureList::IsEnabled(kAllowANGLEPassthroughShaders);
}
void GetANGLEFeaturesFromCommandLineAndFinch(
const base::CommandLine* command_line,
std::vector<std::string>& enabled_angle_features,
std::vector<std::string>& disabled_angle_features) {
SplitAndAppendANGLEFeatureList(
command_line->GetSwitchValueASCII(switches::kEnableANGLEFeatures),
enabled_angle_features);
SplitAndAppendANGLEFeatureList(
command_line->GetSwitchValueASCII(switches::kDisableANGLEFeatures),
disabled_angle_features);
if (base::FeatureList::IsEnabled(kForceANGLEFeatures)) {
SplitAndAppendANGLEFeatureList(kForcedANGLEEnabledFeaturesFP.Get(),
enabled_angle_features);
SplitAndAppendANGLEFeatureList(kForcedANGLEDisabledFeaturesFP.Get(),
disabled_angle_features);
}
}
#if BUILDFLAG(ENABLE_SWIFTSHADER)
bool IsSwiftShaderAllowedByCommandLine(const base::CommandLine* command_line) {
// If the switch to opt-into unsafe SwiftShader is present, always allow
// SwiftShader.
if (command_line->HasSwitch(switches::kEnableUnsafeSwiftShader)) {
return true;
}
std::string angle_name =
command_line->GetSwitchValueASCII(switches::kUseANGLE);
if (angle_name == gl::kANGLEImplementationSwiftShaderName) {
// If SwiftShader is specifically requested with the --use-angle command
// line flag, allow it.
return true;
}
return false;
}
// Allow fallback to SwfitShader without command line flags during the
// deprecation period.
BASE_FEATURE(kAllowSwiftShaderFallback, base::FEATURE_ENABLED_BY_DEFAULT);
bool IsSwiftShaderAllowedByFeature() {
return base::FeatureList::IsEnabled(kAllowSwiftShaderFallback);
}
#else
bool IsSwiftShaderAllowedByCommandLine(const base::CommandLine*) {
return false;
}
bool IsSwiftShaderAllowedByFeature() {
return false;
}
#endif
bool IsSwiftShaderAllowed(const base::CommandLine* command_line) {
return IsSwiftShaderAllowedByCommandLine(command_line) ||
IsSwiftShaderAllowedByFeature();
}
#if BUILDFLAG(IS_WIN)
BASE_FEATURE(kAllowD3D11WarpFallback, base::FEATURE_DISABLED_BY_DEFAULT);
bool IsWARPAllowedByFeature() {
return base::FeatureList::IsEnabled(kAllowD3D11WarpFallback);
}
#else
bool IsWARPAllowedByFeature() {
return false;
}
#endif
bool IsAnySoftwareGLAllowed(const base::CommandLine* command_line) {
#if BUILDFLAG(IS_WIN)
if (base::FeatureList::IsEnabled(kAllowD3D11WarpFallback)) {
return true;
}
#endif
return IsSwiftShaderAllowed(command_line);
}
BASE_FEATURE(kAllowSoftwareGLFallbackDueToCrashes,
base::FEATURE_ENABLED_BY_DEFAULT);
bool IsSoftwareGLFallbackDueToCrashesAllowed(
const base::CommandLine* command_line) {
if (!IsAnySoftwareGLAllowed(command_line)) {
return false;
}
return base::FeatureList::IsEnabled(kAllowSoftwareGLFallbackDueToCrashes);
}
base::TimeDelta GetGLCompileShaderDelay() {
#if BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
if (UsePassthroughCommandDecoder()) {
return base::TimeDelta();
}
if (!base::FeatureList::IsEnabled(kAddDelayToGLCompileShader)) {
return base::TimeDelta();
}
return kGLCompileShaderDelay.Get();
#else
return base::TimeDelta();
#endif // BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
}
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kAndroidLimitRgb565DisplayToApi32,
base::FEATURE_ENABLED_BY_DEFAULT);
bool PreferRGB565ResourcesForDisplay() {
return base::SysInfo::AmountOfPhysicalMemory().InMiB() <= 512 &&
(base::android::android_info::sdk_int() <=
base::android::android_info::SDK_VERSION_Sv2 ||
!base::FeatureList::IsEnabled(kAndroidLimitRgb565DisplayToApi32));
}
#endif
} // namespace features