#include "components/viz/common/features.h"
#include <algorithm>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_split.h"
#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "components/viz/common/switches.h"
#include "components/viz/common/viz_utils.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_switches.h"
#include "media/media_buildflags.h"
#include "ui/gl/gl_switches.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/device_info.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif
namespace features {
#if BUILDFLAG(IS_ARKWEB)
BASE_FEATURE(kExtremeThrottle,
"kExtremeThrottle",
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE_PARAM(double,
kExtremeThrottleFrameRate,
&kExtremeThrottle,
"kExtremeThrottleFrameRate",
2);
#endif
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kAndroidAnimatedProgressBarInViz,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kAndroidBrowserControlsInViz, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kAndroidBcivBottomControls, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kAndroidDumpForBadCompositedUiState,
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kBackForwardTransitionsSameDocSharedImage,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kBackdropFilterMirrorEdgeMode, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kUseDrmBlackFullscreenOptimization,
#if BUILDFLAG(IS_CHROMEOS)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
);
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kUseFrameIntervalDeciderAdaptiveFrameRate,
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kTemporalSkipOverlaysWithRootCopyOutputRequests,
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kUseMultipleOverlays,
#if BUILDFLAG(IS_CHROMEOS)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
);
const char kMaxOverlaysParam[] = "max_overlays";
BASE_FEATURE(kDelegatedCompositing, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kAvoidDuplicateDelayBeginFrame, base::FEATURE_DISABLED_BY_DEFAULT);
const char kDrawQuadSplit[] = "num_of_splits";
BASE_FEATURE(kDrawQuadSplitLimit, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kEnableRenderPassDrawQuadCullingOptimization,
base::FEATURE_ENABLED_BY_DEFAULT);
constexpr base::FeatureParam<DelegatedCompositingMode>::Option
kDelegatedCompositingModeOption[] = {
{DelegatedCompositingMode::kFull, "full"},
#if BUILDFLAG(IS_WIN)
{DelegatedCompositingMode::kLimitToUi, "limit_to_ui"},
#endif
};
const base::FeatureParam<DelegatedCompositingMode>
kDelegatedCompositingModeParam = {
&kDelegatedCompositing,
"mode",
#if BUILDFLAG(IS_WIN)
DelegatedCompositingMode::kLimitToUi,
#else
DelegatedCompositingMode::kFull,
#endif
&kDelegatedCompositingModeOption,
};
#if BUILDFLAG(IS_WIN)
BASE_FEATURE(kDCompSurfacesForDelegatedInk, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kRemoveRedirectionBitmap, base::FEATURE_ENABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kVizFrameSubmissionForWebView, base::FEATURE_DISABLED_BY_DEFAULT);
#if BUILDFLAG(IS_FUCHSIA)
BASE_FEATURE(kUseSkiaOutputDeviceBufferQueue, base::FEATURE_ENABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kWebRtcLogCapturePipeline, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kWebViewVulkanIntermediateBuffer,
base::FEATURE_DISABLED_BY_DEFAULT);
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kUseSurfaceLayerForVideoDefault, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kWebViewNewInvalidateHeuristic, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kWebViewEnableADPF, base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kWebViewADPFSocManufacturerAllowlist{
&kWebViewEnableADPF, "webview_soc_manufacturer_allowlist", "Google"};
const base::FeatureParam<std::string> kWebViewADPFSocManufacturerBlocklist{
&kWebViewEnableADPF, "webview_soc_manufacturer_blocklist", ""};
BASE_FEATURE(kWebViewEnableADPFRendererMain, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kWebViewEnableADPFGpuMain, base::FEATURE_ENABLED_BY_DEFAULT);
#endif
#if BUILDFLAG(IS_APPLE)
BASE_FEATURE(kCALayerNewLimit, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<int> kCALayerNewLimitDefault{&kCALayerNewLimit,
"default", -1};
const base::FeatureParam<int> kCALayerNewLimitManyVideos{&kCALayerNewLimit,
"many-videos", -1};
#endif
#if BUILDFLAG(IS_MAC)
BASE_FEATURE(kVSyncAlignedPresent, base::FEATURE_ENABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kAckCopyOutputRequestEarlyForViewTransition,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kAllowUndamagedNonrootRenderPassToSkip,
#if BUILDFLAG(IS_MAC)
base::FEATURE_ENABLED_BY_DEFAULT);
#else
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kAllowForceMergeRenderPassWithRequireOverlayQuads,
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kOnBeginFrameThrottleVideo,
#if BUILDFLAG(IS_ANDROID)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
);
BASE_FEATURE(kAdpf, base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kADPFSocManufacturerAllowlist{
&kAdpf, "soc_manufacturer_allowlist", "Google"};
const base::FeatureParam<std::string> kADPFSocManufacturerBlocklist{
&kAdpf, "soc_manufacturer_blocklist", ""};
BASE_FEATURE(kEnableADPFScrollBoost, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta> kADPFBoostTimeout{
&kEnableADPFScrollBoost, "adpf_boost_mode_timeout",
base::Milliseconds(200)};
BASE_FEATURE(kEnableInteractiveOnlyADPFRenderer,
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kEnableADPFSeparateRendererMainSession,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kEnableADPFSetThreads, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kEnableADPFWorkloadIncreaseOnPageLoad,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kEnableADPFWorkloadReset, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kAckOnSurfaceActivationWhenInteractive,
base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<int>
kNumCooldownFramesForAckOnSurfaceActivationDuringInteraction{
&kAckOnSurfaceActivationWhenInteractive, "frames", 3};
BASE_FEATURE(kUseDisplaySDRMaxLuminanceNits, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kHideDelegatedFrameHostMac, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kEvictionUnlocksResources, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kSingleVideoFrameRateThrottling,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kShutdownForFailedChannelCreation,
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kShouldLogFrameQuadInfo, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kBatchResourceRelease, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kNoLateBeginFrames, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kLastVSyncArgsKillswitch, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kVizDirectCompositorThreadIpcNonRoot,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kVizDirectCompositorThreadIpcFrameSinkManager,
base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kVizNullHypothesis, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kUse90HzSwapChainCountFor72fps, base::FEATURE_ENABLED_BY_DEFAULT);
#if BUILDFLAG(IS_CHROMEOS)
BASE_FEATURE(kCrosContentAdjustedRefreshRate,
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
BASE_FEATURE(kNoCompositorFrameAcks, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<int> kNumberPendingFramesUntilThrottle{
&kNoCompositorFrameAcks, "pending_frames", 1};
BASE_FEATURE(kDisplaySchedulerAsClient, base::FEATURE_DISABLED_BY_DEFAULT);
int DrawQuadSplitLimit() {
constexpr int kDefaultDrawQuadSplitLimit = 5;
constexpr int kMinDrawQuadSplitLimit = 1;
constexpr int kMaxDrawQuadSplitLimit = 15;
const int split_limit = base::GetFieldTrialParamByFeatureAsInt(
kDrawQuadSplitLimit, kDrawQuadSplit, kDefaultDrawQuadSplitLimit);
return std::clamp(split_limit, kMinDrawQuadSplitLimit,
kMaxDrawQuadSplitLimit);
}
bool IsRenderPassDrawQuadCullingOptimizationEnabled() {
static bool is_enabled = base::FeatureList::IsEnabled(
kEnableRenderPassDrawQuadCullingOptimization);
return is_enabled;
}
bool IsBackForwardTransitionsSameDocSharedImageEnabled() {
return base::FeatureList::IsEnabled(
kBackForwardTransitionsSameDocSharedImage);
}
bool IsDelegatedCompositingEnabled() {
return base::FeatureList::IsEnabled(kDelegatedCompositing);
}
bool IsVizDirectCompositorThreadIpcNonRootEnabled() {
return base::FeatureList::IsEnabled(kVizDirectCompositorThreadIpcNonRoot);
}
bool IsVizDirectCompositorThreadIpcFrameSinkManagerEnabled() {
return base::FeatureList::IsEnabled(
kVizDirectCompositorThreadIpcFrameSinkManager);
}
bool IsUsingVizFrameSubmissionForWebView() {
return base::FeatureList::IsEnabled(kVizFrameSubmissionForWebView);
}
bool ShouldWebRtcLogCapturePipeline() {
return base::FeatureList::IsEnabled(kWebRtcLogCapturePipeline);
}
#if BUILDFLAG(IS_ANDROID)
bool UseWebViewNewInvalidateHeuristic() {
if (base::android::device_info::is_tv()) {
return base::FeatureList::IsEnabled(kWebViewSurfaceControlForTV);
}
return base::FeatureList::IsEnabled(kWebViewNewInvalidateHeuristic);
}
#endif
bool UseSurfaceLayerForVideo() {
#if BUILDFLAG(IS_ANDROID)
if (UseWebViewNewInvalidateHeuristic()) {
return true;
}
if (::features::IsAndroidSurfaceControlEnabled()) {
return true;
}
return base::FeatureList::IsEnabled(kUseSurfaceLayerForVideoDefault);
#else
return true;
#endif
}
int MaxOverlaysConsidered() {
if (!base::FeatureList::IsEnabled(kUseMultipleOverlays)) {
return 1;
}
return base::GetFieldTrialParamByFeatureAsInt(kUseMultipleOverlays,
kMaxOverlaysParam, 8);
}
bool ShouldOnBeginFrameThrottleVideo() {
return base::FeatureList::IsEnabled(features::kOnBeginFrameThrottleVideo);
}
bool ShouldAckOnSurfaceActivationWhenInteractive() {
return base::FeatureList::IsEnabled(
features::kAckOnSurfaceActivationWhenInteractive);
}
bool Use90HzSwapChainCountFor72fps() {
return base::FeatureList::IsEnabled(kUse90HzSwapChainCountFor72fps);
}
std::optional<uint64_t>
NumCooldownFramesForAckOnSurfaceActivationDuringInteraction() {
if (!ShouldAckOnSurfaceActivationWhenInteractive()) {
return std::nullopt;
}
CHECK_GE(kNumCooldownFramesForAckOnSurfaceActivationDuringInteraction.Get(),
0)
<< "The number of cooldown frames must be non-negative";
return static_cast<uint64_t>(
kNumCooldownFramesForAckOnSurfaceActivationDuringInteraction.Get());
}
bool ShouldLogFrameQuadInfo() {
return base::FeatureList::IsEnabled(features::kShouldLogFrameQuadInfo);
}
#if BUILDFLAG(IS_MAC)
bool IsVSyncAlignedPresentEnabled() {
return base::FeatureList::IsEnabled(features::kVSyncAlignedPresent);
}
#endif
#if BUILDFLAG(IS_CHROMEOS)
bool IsCrosContentAdjustedRefreshRateEnabled() {
return base::FeatureList::IsEnabled(kCrosContentAdjustedRefreshRate);
}
#endif
#if BUILDFLAG(IS_WIN)
bool ShouldRemoveRedirectionBitmap() {
if (base::win::GetVersion() < base::win::Version::WIN11_22H2) {
return false;
}
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableDirectComposition)) {
return false;
}
if (command_line->HasSwitch(switches::kOverrideUseSoftwareGLForTests)) {
return false;
}
const std::string angle_backend =
command_line->GetSwitchValueASCII(switches::kUseANGLE);
if (angle_backend == gl::kANGLEImplementationD3D9Name ||
angle_backend == gl::kANGLEImplementationOpenGLName) {
return false;
}
return base::FeatureList::IsEnabled(kRemoveRedirectionBitmap);
}
#endif
#if BUILDFLAG(IS_ANDROID)
bool IsAndroidAnimatedProgressBarInVizEnabled() {
return base::FeatureList::IsEnabled(
features::kAndroidAnimatedProgressBarInViz);
}
bool IsBcivBottomControlsEnabled() {
return base::FeatureList::IsEnabled(features::kAndroidBcivBottomControls);
}
bool IsBrowserControlsInVizEnabled() {
return base::FeatureList::IsEnabled(features::kAndroidBrowserControlsInViz);
}
bool ShouldUseAdpfForSoc(std::string_view soc_allowlist,
std::string_view soc_blocklist,
std::string_view soc) {
std::vector<std::string_view> allowlist = base::SplitStringPiece(
soc_allowlist, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::string blocklist_param = features::kADPFSocManufacturerBlocklist.Get();
std::vector<std::string_view> blocklist = base::SplitStringPiece(
soc_blocklist, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (allowlist.empty()) {
return !base::Contains(blocklist, soc);
}
return base::Contains(allowlist, soc);
}
#endif
bool ShouldAckCOREarlyForViewTransition() {
return base::FeatureList::IsEnabled(
features::kAckCopyOutputRequestEarlyForViewTransition);
}
}