chromium/gpu/config/gpu_finch_features.cc

// 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_switches.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  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#include "base/system/sys_info.h"
#endif  // BUILDFLAG(IS_MAC)

namespace features {
namespace {

#if BUILDFLAG(IS_ANDROID)
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  // BUILDFLAG(IS_ANDROID)

}  // namespace

// Used to limit GL version to 2.0 for skia raster and compositing.
BASE_FEATURE();

#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);

BASE_FEATURE(kWebViewSurfaceControlForTV,
             "WebViewSurfaceControlForTV",
             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);

// 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*"};

// Used to relax the limit of AImageReader max queue size to 1 for Android Tvs.
// Currently for all android tv except the ones in this list will have max
// queue size of 1 image.
BASE_FEATURE(kRelaxLimitAImageReaderMaxSizeToOne,
             "RelaxLimitAImageReaderMaxSizeToOne",
             base::FEATURE_ENABLED_BY_DEFAULT);

// List of devices on which to relax the restriction of max queue size of 1 for
// AImageReader.
const base::FeatureParam<std::string>
    kRelaxLimitAImageReaderMaxSizeToOneSoCBlocklist{
        &kRelaxLimitAImageReaderMaxSizeToOne,
        "RelaxLimitAImageReaderMaxSizeToOneSoCBlocklist", "*Broadcom*"};
const base::FeatureParam<std::string>
    kRelaxLimitAImageReaderMaxSizeToOneManufacturerBlocklist{
        &kRelaxLimitAImageReaderMaxSizeToOne,
        "RelaxLimitAImageReaderMaxSizeToOneManufacturerBlocklist",
        "*Broadcom*"};
const base::FeatureParam<std::string>
    kRelaxLimitAImageReaderMaxSizeToOneDeviceBlocklist{
        &kRelaxLimitAImageReaderMaxSizeToOne,
        "RelaxLimitAImageReaderMaxSizeToOneDeviceBlocklist", ""};
const base::FeatureParam<std::string>
    kRelaxLimitAImageReaderMaxSizeToOneModelBlocklist{
        &kRelaxLimitAImageReaderMaxSizeToOne,
        "RelaxLimitAImageReaderMaxSizeToOneModelBlocklist", ""};

// 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();

#if !BUILDFLAG(IS_ANDROID)
// Enables the use of out of process rasterization for canvas.
BASE_FEATURE();
#endif

// Enables the use of MSAA in skia on Ice Lake and later intel architectures.
BASE_FEATURE();

// When enabled, Dawn SharedImage representations use the internal usages passed
// by their clients when creating textures rather than using custom hardcoded
// internal usages. Serves as killswitch while we roll out this transition.
// TODO(crbug.com/339171225): Remove post-safe rollout.
BASE_FEATURE();

#if BUILDFLAG(IS_WIN)
// 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);
#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

// When enabled, Grshader disk cache will be cleared on startup if any cache
// entry prefix does not match with the current prefix. prefix is made up of
// various parameters like chrome version, driver version etc.
BASE_FEATURE();

// 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();

// 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();

// 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 kWebViewDrawFunctorUsesVulkan instead of this.
BASE_FEATURE();

BASE_FEATURE();

// Enable WebGPU on gpu service side only. This is used with origin trial and
// enabled by default on supported platforms.
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || \
    BUILDFLAG(IS_ANDROID)
#define WEBGPU_ENABLED
#else
#define WEBGPU_ENABLED
#endif
BASE_FEATURE();
BASE_FEATURE();
#undef WEBGPU_ENABLED

// List of WebGPU feature names, delimited by ,
// The FeatureParam may be overridden via Finch config, or via the command line
// For example:
//   --enable-field-trial-config \
//   --force-fieldtrial-params=WebGPU.Enabled:UnsafeFeatures/timestamp-query%2Cshader-f16
// Note that the comma should be URL-encoded.
const base::FeatureParam<std::string> kWebGPUUnsafeFeatures{};
// List of WGSL feature names, delimited by ,
// The FeatureParam may be overridden via Finch config, or via the command line
// For example:
//   --enable-field-trial-config \
//   --force-fieldtrial-params=WebGPU.Enabled:UnsafeWGSLFeatures/feature_1%2Cfeature_2
// Note that the comma should be URL-encoded.
const base::FeatureParam<std::string> kWGSLUnsafeFeatures{};

BASE_FEATURE();
BASE_FEATURE();

#if BUILDFLAG(IS_ANDROID)

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

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

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

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", ""};

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

// Blocklists meant for DrDc.
// crbug.com/1294648, crbug.com/1397578: the screen flickers.
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|ASUS_I006D|ASUS_I004D|bacon"};

// 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.
// Note: This can also be overridden by
// --enable-skia-graphite & --disable-skia-graphite.
BASE_FEATURE();

BASE_FEATURE();

// Whether the Dawn "skip_validation" toggle is enabled for Skia Graphite.
const base::FeatureParam<bool> kSkiaGraphiteDawnSkipValidation{};

// Whether Dawn backend validation is enabled for Skia Graphite.
const base::FeatureParam<bool> kSkiaGraphiteDawnBackendValidation{};

#if BUILDFLAG(IS_WIN)
BASE_FEATURE(kSkiaGraphiteDawnUseD3D12,
             "SkiaGraphiteDawnUseD3D12",
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif

// Enable persistent storage of VkPipelineCache data.
BASE_FEATURE();

// Enabling this will make the GPU decode path use a mock implementation of
// discardable memory.
BASE_FEATURE();

// Use a 100-command limit before forcing context switch per command buffer
// instead of 20.
BASE_FEATURE();

// Prune transfer cache entries not accessed recently. This also turns off
// similar logic in cc::GpuImageDecodeCache which is the largest (often single)
// client of transfer cache.
BASE_FEATURE();

// Using the new SchedulerDfs GPU scheduler.
BASE_FEATURE();

// On platforms with delegated compositing, try to release overlays later, when
// no new frames are swapped.
BASE_FEATURE();

// Use d3d11 UpdateSubresource() (instead of a staging texture) to upload pixels
// to textures.
#if BUILDFLAG(IS_WIN)
BASE_FEATURE(kD3DBackingUploadWithUpdateSubresource,
             "D3DBackingUploadWithUpdateSubresource",
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif

// This feature allows viz to handle overlays' swap failures instead of loosing a context and
// restarting a gpu service.
BASE_FEATURE();

bool UseGles2ForOopR() {}

bool IsUsingVulkan() {}

bool IsDrDcEnabled() {}

bool IsUsingThreadSafeMediaForWebView() {}

// 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() {}

namespace {
bool IsSkiaGraphiteSupportedByDevice(const base::CommandLine* command_line) {}
}  // namespace

bool IsSkiaGraphiteEnabled(const base::CommandLine* command_line) {}

// Set up such that service side purge depends on the client side purge feature
// being enabled. And enabling service side purge disables client purge
bool EnablePurgeGpuImageDecodeCache() {}
bool EnablePruneOldTransferCacheEntries() {}

bool IsCanvasOopRasterizationEnabled() {}

#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
  // TODO(crbug.com/40224845): Can we revisit this now that GLImage no longer
  // exists?
  if (IsDeviceBlocked(base::android::BuildInfo::GetInstance()->device(),
                      "Hammer_Energy_2")) {
    return false;
  }

  return base::FeatureList::IsEnabled(kAImageReader) &&
         base::android::EnableAndroidImageReader();
}

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()) {
    // We decouple experiments between ATV and the rest of the users by using
    // different flags here.
    if (base::android::BuildInfo::GetInstance()->is_tv()) {
      return base::FeatureList::IsEnabled(kWebViewSurfaceControlForTV);
    } else {
      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()) {
    // For the android Tvs which are in the below list, we are relaxing this
    // restrictions as those are able to create AImageReader with more than 1
    // images. This helps in removing the flickering seen which can happen with
    // only 1 image. Also note that we should use soc_manufacturer instead of
    // manufacturer when available as sometimes manufacturer field gets
    // modified by vendors.

    const auto* build_info = base::android::BuildInfo::GetInstance();

    if (IsDeviceBlocked(
            build_info->soc_manufacturer(),
            kRelaxLimitAImageReaderMaxSizeToOneSoCBlocklist.Get())) {
      return false;
    }
    if (IsDeviceBlocked(
            build_info->manufacturer(),
            kRelaxLimitAImageReaderMaxSizeToOneManufacturerBlocklist.Get())) {
      return false;
    }
    if (IsDeviceBlocked(
            build_info->device(),
            kRelaxLimitAImageReaderMaxSizeToOneDeviceBlocklist.Get())) {
      return false;
    }
    if (IsDeviceBlocked(
            build_info->model(),
            kRelaxLimitAImageReaderMaxSizeToOneModelBlocklist.Get())) {
      return false;
    }

    return true;
  }

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

bool IncreaseBufferCountForHighFrameRate() {
  // TODO(crbug.com/40767562): 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

// When this flag and kUseGpuSchedulerDfs are both enabled, stops using
// gpu::SyncPointOrderData for sync point validation, uses gpu::TaskGraph
// instead.
// Graph-based validation doesn't require sync point releases are submitted to
// the scheduler prior to their corresponding waits. Therefore it allows to
// remove the synchronous flush done by VerifySyncTokens().
//
// TODO(b/324276400): Work in progress.
BASE_FEATURE();

bool IsSyncPointGraphValidationEnabled() {}

}  // namespace features