38808be4创建于 2025年1月19日历史提交
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/config/gpu_finch_features.h"

#include "base/command_line.h"
#include "base/feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "gpu/config/gpu_switches.h"
#include "ui/gl/gl_features.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/gl_utils.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/android_image_reader_compat.h"
#include "base/android/build_info.h"
#include "base/android/sys_utils.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/pattern.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "ui/gfx/android/android_surface_control_compat.h"
#endif

#if defined(OHOS_DRDC)
#include "content/public/common/content_switches.h"
#include "ohos_adapter_helper.h"
#endif // defined(OHOS_DRDC)

namespace features {
namespace {

#if BUILDFLAG(IS_ANDROID)
bool FieldIsInBlocklist(const char* current_value, std::string blocklist_str) {
  std::vector<std::string> blocklist = base::SplitString(
      blocklist_str, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  for (const std::string& blocklisted_value : blocklist) {
    if (base::StartsWith(current_value, blocklisted_value,
                         base::CompareCase::INSENSITIVE_ASCII)) {
      return true;
    }
  }
  return false;
}

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

}  // namespace

// Used to limit GL version to 2.0 for skia raster and compositing.
BASE_FEATURE(kUseGles2ForOopR,
             "UseGles2ForOopR",
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || \
    BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
             base::FEATURE_DISABLED_BY_DEFAULT
#else
             base::FEATURE_ENABLED_BY_DEFAULT
#endif
);

#if BUILDFLAG(IS_ANDROID)
// Use android SurfaceControl API for managing display compositor's buffer queue
// and using overlays on Android. Also used by webview to disable surface
// SurfaceControl.
BASE_FEATURE(kAndroidSurfaceControl,
             "AndroidSurfaceControl",
             base::FEATURE_ENABLED_BY_DEFAULT);

// https://crbug.com/1176185 List of devices on which SurfaceControl should be
// disabled.
const base::FeatureParam<std::string> kAndroidSurfaceControlDeviceBlocklist{
    &kAndroidSurfaceControl, "AndroidSurfaceControlDeviceBlocklist",
    "capri|caprip"};

// List of models on which SurfaceControl should be disabled.
const base::FeatureParam<std::string> kAndroidSurfaceControlModelBlocklist{
    &kAndroidSurfaceControl, "AndroidSurfaceControlModelBlocklist",
    "SM-F9*|SM-W202?|SCV44|SCG05|SCG11|SC-55B"};

// Hardware Overlays for WebView.
BASE_FEATURE(kWebViewSurfaceControl,
             "WebViewSurfaceControl",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Use thread-safe media path on WebView.
BASE_FEATURE(kWebViewThreadSafeMedia,
             "WebViewThreadSafeMedia",
             base::FEATURE_DISABLED_BY_DEFAULT);

// This is used as default state because it's different for webview and chrome.
// WebView hardcodes this as enabled in AwMainDelegate.
BASE_FEATURE(kWebViewThreadSafeMediaDefault,
             "WebViewThreadSafeMediaDefault",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Use AImageReader for MediaCodec and MediaPlyer on android.
BASE_FEATURE(kAImageReader, "AImageReader", base::FEATURE_ENABLED_BY_DEFAULT);

// If webview-draw-functor-uses-vulkan is set, use vulkan for composite and
// raster.
BASE_FEATURE(kWebViewVulkan, "WebViewVulkan", base::FEATURE_ENABLED_BY_DEFAULT);

// Used to limit AImageReader max queue size to 1 since many devices especially
// android Tv devices do not support more than 1 images.
BASE_FEATURE(kLimitAImageReaderMaxSizeToOne,
             "LimitAImageReaderMaxSizeToOne",
             base::FEATURE_ENABLED_BY_DEFAULT);

// List of devices on which to limit AImageReader max queue size to 1.
const base::FeatureParam<std::string> kLimitAImageReaderMaxSizeToOneBlocklist{
    &kLimitAImageReaderMaxSizeToOne, "LimitAImageReaderMaxSizeToOneBlocklist",
    "MIBOX|*ODROID*"};

// Increase number of buffers and pipeline depth for high frame rate devices.
BASE_FEATURE(kIncreaseBufferCountForHighFrameRate,
             "IncreaseBufferCountForHighFrameRate",
             base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<std::string>
    kDisableIncreaseBufferCountForHighFrameRate{
        &kIncreaseBufferCountForHighFrameRate,
        "DisableIncreaseBufferCountForHighFrameRate", ""};
#endif

// Enable GPU Rasterization by default. This can still be overridden by
// --enable-gpu-rasterization or --disable-gpu-rasterization.
// DefaultEnableGpuRasterization has launched on Mac, Windows, ChromeOS,
// Android and Linux.
BASE_FEATURE(kDefaultEnableGpuRasterization,
             "DefaultEnableGpuRasterization",
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || \
    BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

// Enables the use of out of process rasterization for canvas.
BASE_FEATURE(kCanvasOopRasterization,
             "CanvasOopRasterization",
#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_IOS) || BUILDFLAG(IS_WIN) || \
    (BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64)) || BUILDFLAG(IS_OHOS)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

// Enables the use of MSAA in skia on Ice Lake and later intel architectures.
BASE_FEATURE(kEnableMSAAOnNewIntelGPUs,
             "EnableMSAAOnNewIntelGPUs",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables the use of ANGLE validation for non-WebGL contexts.
BASE_FEATURE(kDefaultEnableANGLEValidation,
             "DefaultEnableANGLEValidation",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables canvas to free its resources by default when it's running in
// the background.
BASE_FEATURE(kCanvasContextLostInBackground,
             "CanvasContextLostInBackground",
             base::FEATURE_DISABLED_BY_DEFAULT);

#if BUILDFLAG(IS_WIN)
// Use a high priority for GPU process on Windows.
BASE_FEATURE(kGpuProcessHighPriorityWin,
             "GpuProcessHighPriorityWin",
             base::FEATURE_ENABLED_BY_DEFAULT);

// Disable overlay promotion for clear video quads when their MPO quad would
// move.
BASE_FEATURE(kDisableVideoOverlayIfMoving,
             "DisableVideoOverlayIfMoving",
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kNoUndamagedOverlayPromotion,
             "NoUndamagedOverlayPromotion",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Use a DCompPresenter as the root surface, instead of a
// DirectCompositionSurfaceWin. DCompPresenter is surface-less and the actual
// allocation of the root surface will be owned by the
// SkiaOutputDeviceDCompPresenter.
BASE_FEATURE(kDCompPresenter,
             "DCompPresenter",
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_IOS)
// If enabled, the TASK_CATEGORY_POLICY value of the GPU process will be
// adjusted to match the one from the browser process every time it changes.
BASE_FEATURE(kAdjustGpuProcessPriority,
             "AdjustGpuProcessPriority",
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif

// Causes us to use the SharedImageManager, removing support for the old
// mailbox system. Any consumers of the GPU process using the old mailbox
// system will experience undefined results.
BASE_FEATURE(kSharedImageManager,
             "SharedImageManager",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Controls the decode acceleration of JPEG images (as opposed to camera
// captures) in Chrome OS using the VA-API.
// TODO(andrescj): remove or enable by default in Chrome OS once
// https://crbug.com/868400 is resolved.
BASE_FEATURE(kVaapiJpegImageDecodeAcceleration,
             "VaapiJpegImageDecodeAcceleration",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Controls the decode acceleration of WebP images in Chrome OS using the
// VA-API.
// TODO(gildekel): remove or enable by default in Chrome OS once
// https://crbug.com/877694 is resolved.
BASE_FEATURE(kVaapiWebPImageDecodeAcceleration,
             "VaapiWebPImageDecodeAcceleration",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enable Vulkan graphics backend for compositing and rasterization. Defaults to
// native implementation if --use-vulkan flag is not used. Otherwise
// --use-vulkan will be followed.
// Note Android WebView uses kWebViewVulkan instead of this.
BASE_FEATURE(kVulkan,
             "Vulkan",
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

BASE_FEATURE(kEnableDrDc,
             "EnableDrDc",
#if BUILDFLAG(IS_ANDROID)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

BASE_FEATURE(kForceGpuMainThreadToNormalPriorityDrDc,
             "ForceGpuMainThreadToNormalPriorityDrDc",
             base::FEATURE_DISABLED_BY_DEFAULT);

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS)
BASE_FEATURE(kEnableDrDcVulkan,
             "EnableDrDcVulkan",
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_ANDROID)

// Enable WebGPU on gpu service side only. This is used with origin trial and
// enabled by default on supported platforms.
BASE_FEATURE(kWebGPUService,
             "WebGPUService",
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

#if BUILDFLAG(IS_ANDROID)

const base::FeatureParam<std::string> kVulkanBlockListByHardware{
    &kVulkan, "BlockListByHardware", "mt*"};

const base::FeatureParam<std::string> kVulkanBlockListByBrand{
    &kVulkan, "BlockListByBrand", "HONOR"};

const base::FeatureParam<std::string> kVulkanBlockListByDevice{
    &kVulkan, "BlockListByDevice", "OP4863|OP4883"};

const base::FeatureParam<std::string> kVulkanBlockListByAndroidBuildId{
    &kVulkan, "BlockListByAndroidBuildId", ""};

const base::FeatureParam<std::string> kVulkanBlockListByManufacturer{
    &kVulkan, "BlockListByManufacturer", ""};

const base::FeatureParam<std::string> kVulkanBlockListByModel{
    &kVulkan, "BlockListByModel", ""};

const base::FeatureParam<std::string> kVulkanBlockListByBoard{
    &kVulkan, "BlockListByBoard",
    "RM67*|RM68*|k68*|mt6*|oppo67*|oppo68*|QM215|rk30sdk"};

const base::FeatureParam<std::string> kVulkanBlockListByAndroidBuildFP{
    &kVulkan, "BlockListByAndroidBuildFP", ""};

// Blocklists meant for DrDc.
// crbug.com/1294648
const base::FeatureParam<std::string> kDrDcBlockListByDevice{
    &kEnableDrDc, "BlockListByDevice",
    "LF9810_2GB|amber|chopin|secret|a03|SO-51B|on7xelte|j7xelte|F41B|doha|"
    "rk322x_box|a20s|HWMAR|HWSTK-HF|HWPOT-H|b2q|channel|galahad|a32|ellis|"
    "dandelion|tonga|RMX3231"};

// crbug.com/1340059, crbug.com/1340064
const base::FeatureParam<std::string> kDrDcBlockListByModel{
    &kEnableDrDc, "BlockListByModel",
    "SM-J400M|SM-J415F|ONEPLUS A3003|OCTAStream*"};

const base::FeatureParam<std::string> kDrDcBlockListByHardware{
    &kEnableDrDc, "BlockListByHardware", ""};

const base::FeatureParam<std::string> kDrDcBlockListByBrand{
    &kEnableDrDc, "BlockListByBrand", "HONOR"};

const base::FeatureParam<std::string> kDrDcBlockListByAndroidBuildId{
    &kEnableDrDc, "BlockListByAndroidBuildId", ""};

const base::FeatureParam<std::string> kDrDcBlockListByManufacturer{
    &kEnableDrDc, "BlockListByManufacturer", ""};

const base::FeatureParam<std::string> kDrDcBlockListByBoard{
    &kEnableDrDc, "BlockListByBoard", ""};

const base::FeatureParam<std::string> kDrDcBlockListByAndroidBuildFP{
    &kEnableDrDc, "BlockListByAndroidBuildFP", ""};
#endif  // BUILDFLAG(IS_ANDROID)

// Enable Skia Graphite. This will use the Dawn backend by default, but can be
// overridden with command line flags for testing on non-official developer
// builds. See --skia-graphite-backend flag in gpu_switches.h.
BASE_FEATURE(kSkiaGraphite,
             "SkiaUseGraphite",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enable GrShaderCache to use with Vulkan backend.
BASE_FEATURE(kEnableGrShaderCacheForVulkan,
             "EnableGrShaderCacheForVulkan",
             base::FEATURE_ENABLED_BY_DEFAULT);

// Enable report only mode on the GPU watchdog instead of pausing the watchdog
// thread during GPU startup.
BASE_FEATURE(kEnableWatchdogReportOnlyModeOnGpuInit,
             "EnableWatchdogReportOnlyModeOnGpuInit",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enable persistent storage of VkPipelineCache data.
BASE_FEATURE(kEnableVkPipelineCache,
             "EnableVkPipelineCache",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enable Skia reduceOpsTaskSplitting to reduce render passes.
BASE_FEATURE(kReduceOpsTaskSplitting,
             "ReduceOpsTaskSplitting",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enabling this will make the GPU decode path use a mock implementation of
// discardable memory.
BASE_FEATURE(kNoDiscardableMemoryForGpuDecodePath,
             "NoDiscardableMemoryForGpuDecodePath",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Use a 100-command limit before forcing context switch per command buffer
// instead of 20.
BASE_FEATURE(kIncreasedCmdBufferParseSlice,
             "IncreasedCmdBufferParseSlice",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Kill switch for forcing restart GPU with context loss.
// See https://crbug.com/1172229 for detail.
BASE_FEATURE(kForceRestartGpuKillSwitch,
             "ForceRestartGpuKillSwitch",
             base::FEATURE_ENABLED_BY_DEFAULT);

// Using the new SchedulerDfs GPU scheduler.
BASE_FEATURE(kUseGpuSchedulerDfs,
             "UseGpuSchedulerDfs",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enable YUV<->RGB conversion for video clients through passthrough command
// decoder.
BASE_FEATURE(kPassthroughYuvRgbConversion,
             "PassthroughYuvRgbConversion",
             base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, the validating command decoder always obtains the size to use
// from the source texture when copying textures, rather than first checking if
// there is a GLImage present and using its size if so.
BASE_FEATURE(kCmdDecoderAlwaysGetSizeFromSourceTexture,
             "CmdDecoderAlwaysGetSizeFromSourceTexture",
             base::FEATURE_ENABLED_BY_DEFAULT);

// When the application is in background, whether to perform immediate GPU
// cleanup when executing deferred requests.
BASE_FEATURE(kGpuCleanupInBackground,
             "GpuCleanupInBackground",
             base::FEATURE_DISABLED_BY_DEFAULT);

bool UseGles2ForOopR() {
#if BUILDFLAG(IS_ANDROID)
  // GLS3 + passthrough decoder break many tests on Android.
  // TODO(crbug.com/1044287): use GLES3 with passthrough decoder.
  if (gl::UsePassthroughCommandDecoder(base::CommandLine::ForCurrentProcess()))
    return true;
#endif
  return base::FeatureList::IsEnabled(features::kUseGles2ForOopR);
}

bool IsUsingVulkan() {
#if BUILDFLAG(IS_ANDROID)
  // Force on if Vulkan feature is enabled from command line.
  base::FeatureList* feature_list = base::FeatureList::GetInstance();
  if (feature_list &&
      feature_list->IsFeatureOverriddenFromCommandLine(
          features::kVulkan.name, base::FeatureList::OVERRIDE_ENABLE_FEATURE))
    return true;

  // WebView checks, which do not use (and disables) kVulkan.
  // Do this above the Android version check because there are test devices
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kWebViewDrawFunctorUsesVulkan) &&
      base::FeatureList::IsEnabled(kWebViewVulkan)) {
    return true;
  }

  // No support for devices before Q -- exit before checking feature flags
  // so that devices are not counted in finch trials.
  if (base::android::BuildInfo::GetInstance()->sdk_int() <
      base::android::SDK_VERSION_Q)
    return false;

  if (!base::FeatureList::IsEnabled(kVulkan))
    return false;

  // Check block list against build info.
  const auto* build_info = base::android::BuildInfo::GetInstance();
  if (IsDeviceBlocked(build_info->hardware(), kVulkanBlockListByHardware.Get()))
    return false;
  if (IsDeviceBlocked(build_info->brand(), kVulkanBlockListByBrand.Get()))
    return false;
  if (IsDeviceBlocked(build_info->device(), kVulkanBlockListByDevice.Get()))
    return false;
  if (IsDeviceBlocked(build_info->android_build_id(),
                      kVulkanBlockListByAndroidBuildId.Get()))
    return false;
  if (IsDeviceBlocked(build_info->manufacturer(),
                      kVulkanBlockListByManufacturer.Get()))
    return false;
  if (IsDeviceBlocked(build_info->model(), kVulkanBlockListByModel.Get()))
    return false;
  if (IsDeviceBlocked(build_info->board(), kVulkanBlockListByBoard.Get()))
    return false;
  if (IsDeviceBlocked(build_info->android_build_fp(),
                      kVulkanBlockListByAndroidBuildFP.Get()))
    return false;

  return true;

#elif BUILDFLAG(IS_OHOS)
  auto& system_properties_adapter = OHOS::NWeb::OhosAdapterHelper::GetInstance()
                                     .GetSystemPropertiesInstance();
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  bool cmd_value = false;
  if (command_line) {
    cmd_value = command_line->HasSwitch(switches::kOhosEnableVulkan);
  }
  std::string vulkan_enable = system_properties_adapter.GetVulkanStatus();
  LOG(DEBUG) << "vulkan switch config is: " << cmd_value << ", cmd is: " << vulkan_enable;
  if (vulkan_enable == "false") {
    return false;
  } else if (vulkan_enable == "None") {
    return cmd_value;
  } else {
    return true;
  }
#else
  return base::FeatureList::IsEnabled(kVulkan);
#endif
}

bool IsDrDcEnabled() {
#if BUILDFLAG(IS_ANDROID)
  // Enabled on android P+.
  if (base::android::BuildInfo::GetInstance()->sdk_int() <
      base::android::SDK_VERSION_P) {
    return false;
  }

  // DrDc is supported on android MediaPlayer and MCVD path only when
  // AImageReader is enabled. Also DrDc requires AImageReader max size to be
  // at least 2 for each gpu thread. Hence DrDc is disabled on devices which has
  // only 1 image.
  if (!IsAImageReaderEnabled() || LimitAImageReaderMaxSizeToOne())
    return false;

  // Check block list against build info.
  const auto* build_info = base::android::BuildInfo::GetInstance();
  if (IsDeviceBlocked(build_info->device(), kDrDcBlockListByDevice.Get()))
    return false;
  if (IsDeviceBlocked(build_info->model(), kDrDcBlockListByModel.Get()))
    return false;
  if (IsDeviceBlocked(build_info->hardware(), kDrDcBlockListByHardware.Get()))
    return false;
  if (IsDeviceBlocked(build_info->brand(), kDrDcBlockListByBrand.Get()))
    return false;
  if (IsDeviceBlocked(build_info->android_build_id(),
                      kDrDcBlockListByAndroidBuildId.Get()))
    return false;
  if (IsDeviceBlocked(build_info->manufacturer(),
                      kDrDcBlockListByManufacturer.Get()))
    return false;
  if (IsDeviceBlocked(build_info->board(), kDrDcBlockListByBoard.Get()))
    return false;
  if (IsDeviceBlocked(build_info->android_build_fp(),
                      kDrDcBlockListByAndroidBuildFP.Get()))
    return false;

  if (!base::FeatureList::IsEnabled(kEnableDrDc))
    return false;
  return IsUsingVulkan() ? base::FeatureList::IsEnabled(kEnableDrDcVulkan)
                         : true;
#elif defined(OHOS_DRDC)
  if (IsUsingVulkan()) {
    LOG(DEBUG) << "vulkan drdc enabled " << base::FeatureList::IsEnabled(kEnableDrDcVulkan);
    return base::FeatureList::IsEnabled(kEnableDrDcVulkan);
  }
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (command_line) {
      LOG(DEBUG) << "vulkan drdc enabled " <<  command_line->HasSwitch(::switches::kOhosEnableDrDc);
      return command_line->HasSwitch(::switches::kOhosEnableDrDc);
  }
  return false;
#else
  return false;
#endif
}

bool IsGpuMainThreadForcedToNormalPriorityDrDc() {
  // GPU main thread priority is forced to NORMAL only when DrDc is enabled. In
  // that case DrDc thread continues to use DISPLAY thread priority and hence
  // have higher thread priority than GPU main.
  return IsDrDcEnabled() &&
         base::FeatureList::IsEnabled(kForceGpuMainThreadToNormalPriorityDrDc);
}

bool IsUsingThreadSafeMediaForWebView() {
#if BUILDFLAG(IS_ANDROID)
  // SurfaceTexture can't be thread-safe. Also thread safe media code currently
  // requires AImageReader max size to be at least 2 since one image could be
  // accessed by each gpu thread in webview.
  if (!IsAImageReaderEnabled() || LimitAImageReaderMaxSizeToOne())
    return false;

  // If the feature is overridden from command line or finch we will use its
  // value. If not we use kWebViewThreadSafeMediaDefault which is set in
  // AwMainDelegate for WebView.
  base::FeatureList* feature_list = base::FeatureList::GetInstance();
  if (feature_list &&
      feature_list->IsFeatureOverridden(kWebViewThreadSafeMedia.name))
    return base::FeatureList::IsEnabled(kWebViewThreadSafeMedia);

  return base::FeatureList::IsEnabled(kWebViewThreadSafeMediaDefault);
#else
  return false;
#endif
}

// Note that DrDc is also disabled on some of the gpus (crbug.com/1354201).
// Thread safe media will still be used on those gpus which should be fine for
// now as the lock shouldn't have much overhead and is limited to only few gpus.
// This should be fixed/updated later to account for disabled gpus.
bool NeedThreadSafeAndroidMedia() {
  return IsDrDcEnabled() || IsUsingThreadSafeMediaForWebView();
}

bool IsANGLEValidationEnabled() {
  return base::FeatureList::IsEnabled(kDefaultEnableANGLEValidation) &&
         UsePassthroughCommandDecoder();
}

#if BUILDFLAG(IS_ANDROID)
bool IsAImageReaderEnabled() {
  // Device Hammer_Energy_2 seems to be very crash with image reader during
  // gl::GLImageEGL::BindTexImage(). Disable image reader on that device for
  // now. crbug.com/1323921
  if (IsDeviceBlocked(base::android::BuildInfo::GetInstance()->device(),
                      "Hammer_Energy_2")) {
    return false;
  }

  return base::FeatureList::IsEnabled(kAImageReader) &&
         base::android::AndroidImageReader::GetInstance().IsSupported();
}

bool IsAndroidSurfaceControlEnabled() {
  const auto* build_info = base::android::BuildInfo::GetInstance();
  if (IsDeviceBlocked(build_info->device(),
                      kAndroidSurfaceControlDeviceBlocklist.Get()) ||
      (IsDeviceBlocked(build_info->model(),
                       kAndroidSurfaceControlModelBlocklist.Get()) &&
       // Power issue due to pre-rotate in the models has been fixed in S_V2.
       // crbug.com/1328738
       build_info->sdk_int() <= base::android::SDK_VERSION_S)) {
    return false;
  }

  if (!gfx::SurfaceControl::IsSupported())
    return false;

  // We can use surface control only with AImageReader.
  if (!IsAImageReaderEnabled())
    return false;

  // SurfaceControl requires at least 3 frames in flight.
  if (LimitAImageReaderMaxSizeToOne())
    return false;

  // On WebView we require thread-safe media to use SurfaceControl
  if (IsUsingThreadSafeMediaForWebView()) {
    return base::FeatureList::IsEnabled(kWebViewSurfaceControl);
  }

  return base::FeatureList::IsEnabled(kAndroidSurfaceControl);
}

// Many devices do not support more than 1 image to be acquired from the
// AImageReader.(crbug.com/1051705). This method returns true for those
// devices. Currently the list of device model names are sent from server side
// via a finch config file. There is a known device MIBOX for which max size
// should be 1 irrespecticve of the feature LimitAImageReaderMaxSizeToOne
// enabled or not. Get() returns default value even if the feature is disabled.
bool LimitAImageReaderMaxSizeToOne() {
  // Always limit image reader to 1 frame for Android TV. Many TVs doesn't work
  // with more than 1 frame and it's very hard to localize which models do.
  if (base::android::BuildInfo::GetInstance()->is_tv())
    return true;

  return (FieldIsInBlocklist(base::android::BuildInfo::GetInstance()->model(),
                             kLimitAImageReaderMaxSizeToOneBlocklist.Get()));
}

bool IncreaseBufferCountForHighFrameRate() {
  // TODO(crbug.com/1211332): We don't have a way to dynamically adjust number
  // of buffers. So these checks, espeically the RAM one, is to limit the impact
  // of more buffers to devices that can handle them.
  // 8GB of ram with large margin for error.
  constexpr int RAM_8GB_CUTOFF = 7200 * 1024;
  static bool increase =
      base::android::BuildInfo::GetInstance()->sdk_int() >=
          base::android::SdkVersion::SDK_VERSION_R &&
      IsAndroidSurfaceControlEnabled() && IsAImageReaderEnabled() &&
      base::android::SysUtils::AmountOfPhysicalMemoryKB() > RAM_8GB_CUTOFF &&
      base::FeatureList::IsEnabled(kIncreaseBufferCountForHighFrameRate) &&
      !IsDeviceBlocked(base::android::BuildInfo::GetInstance()->device(),
                       kDisableIncreaseBufferCountForHighFrameRate.Get());
  return increase;
}

#endif

}  // namespace features