#include "ui/gl/gl_features.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "build/build_config.h"
#include "ui/gl/gl_switches.h"
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/pattern.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_APPLE)
BASE_FEATURE(kGpuVsync, "GpuVsync", base::FEATURE_DISABLED_BY_DEFAULT);
#else
BASE_FEATURE(kGpuVsync, "GpuVsync", base::FEATURE_ENABLED_BY_DEFAULT);
#endif
#if BUILDFLAG(IS_ANDROID)
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 char* 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
}
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kAndroidFrameDeadline,
"AndroidFrameDeadline",
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
#if BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER)
BASE_FEATURE(kDefaultPassthroughCommandDecoder,
"DefaultPassthroughCommandDecoder",
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
#if BUILDFLAG(IS_MAC)
BASE_FEATURE(kWriteMetalShaderCacheToDisk,
"WriteMetalShaderCacheToDisk",
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kUseBuiltInMetalShaderCache,
"UseBuiltInMetalShaderCache",
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
bool UseGpuVsync() {
return !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuVsync) &&
base::FeatureList::IsEnabled(kGpuVsync);
}
bool IsAndroidFrameDeadlineEnabled() {
#if BUILDFLAG(IS_ANDROID)
static bool enabled =
base::android::BuildInfo::GetInstance()->is_at_least_t() &&
gfx::AChoreographerCompat33::Get().supported &&
gfx::SurfaceControl::SupportsSetFrameTimeline() &&
gfx::SurfaceControl::SupportsSetEnableBackPressure() &&
base::FeatureList::IsEnabled(kAndroidFrameDeadline);
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)
const auto* build_info = base::android::BuildInfo::GetInstance();
if (IsDeviceBlocked(build_info->brand(),
kPassthroughCommandDecoderBlockListByBrand.Get()))
return false;
if (IsDeviceBlocked(build_info->device(),
kPassthroughCommandDecoderBlockListByDevice.Get()))
return false;
if (IsDeviceBlocked(
build_info->android_build_id(),
kPassthroughCommandDecoderBlockListByAndroidBuildId.Get()))
return false;
if (IsDeviceBlocked(build_info->manufacturer(),
kPassthroughCommandDecoderBlockListByManufacturer.Get()))
return false;
if (IsDeviceBlocked(build_info->model(),
kPassthroughCommandDecoderBlockListByModel.Get()))
return false;
if (IsDeviceBlocked(build_info->board(),
kPassthroughCommandDecoderBlockListByBoard.Get()))
return false;
if (IsDeviceBlocked(
build_info->android_build_fp(),
kPassthroughCommandDecoderBlockListByAndroidBuildFP.Get()))
return false;
#endif
return true;
#endif
}
}