tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxConfigManager.cpp (13472B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/gfx/gfxConfigManager.h"
      8 #include "mozilla/gfx/gfxVars.h"
      9 #include "mozilla/Preferences.h"
     10 #include "mozilla/Components.h"
     11 #include "mozilla/StaticPrefs_gfx.h"
     12 #include "mozilla/StaticPrefs_layers.h"
     13 #include "gfxConfig.h"
     14 #include "gfxPlatform.h"
     15 #include "nsIGfxInfo.h"
     16 #include "nsPrintfCString.h"
     17 #include "nsXULAppAPI.h"
     18 
     19 #ifdef XP_WIN
     20 #  include "mozilla/gfx/DeviceManagerDx.h"
     21 #  include "mozilla/gfx/DisplayConfigWindows.h"
     22 #endif
     23 
     24 namespace mozilla {
     25 namespace gfx {
     26 
     27 void gfxConfigManager::Init() {
     28  MOZ_ASSERT(XRE_IsParentProcess());
     29 
     30  EmplaceUserPref("gfx.webrender.compositor", mWrCompositorEnabled);
     31  mWrForceEnabled = gfxPlatform::WebRenderPrefEnabled();
     32  mWrSoftwareForceEnabled = StaticPrefs::gfx_webrender_software_AtStartup();
     33  mWrCompositorForceEnabled =
     34 #ifdef MOZ_WAYLAND
     35      StaticPrefs::gfx_wayland_hdr_AtStartup() ||
     36      StaticPrefs::gfx_wayland_hdr_force_enabled_AtStartup() ||
     37 #endif
     38      StaticPrefs::gfx_webrender_compositor_force_enabled_AtStartup();
     39  mWrForcePartialPresent =
     40      StaticPrefs::gfx_webrender_force_partial_present_AtStartup();
     41  mWrPartialPresent =
     42      StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup() > 0;
     43  EmplaceUserPref(StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(),
     44                  mWrShaderCache);
     45  mWrOptimizedShaders =
     46      StaticPrefs::gfx_webrender_use_optimized_shaders_AtStartup();
     47  mWrScissoredCacheClearsEnabled =
     48      StaticPrefs::gfx_webrender_scissored_cache_clears_enabled_AtStartup();
     49  mWrScissoredCacheClearsForceEnabled = StaticPrefs::
     50      gfx_webrender_scissored_cache_clears_force_enabled_AtStartup();
     51 #ifdef XP_WIN
     52  mWrForceAngle = StaticPrefs::gfx_webrender_force_angle_AtStartup();
     53  mWrForceAngleNoGPUProcess = StaticPrefs::
     54      gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup();
     55  mWrDCompWinEnabled =
     56      Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false);
     57 #endif
     58 
     59  mWrEnvForceEnabled = gfxPlatform::WebRenderEnvvarEnabled();
     60 
     61 #ifdef XP_WIN
     62  DeviceManagerDx::Get()->CheckHardwareStretchingSupport(mHwStretchingSupport);
     63  mScaledResolution = HasScaledResolution();
     64  mWrCompositorDCompRequired = true;
     65 #else
     66  ++mHwStretchingSupport.mBoth;
     67 #endif
     68 
     69 #ifdef MOZ_WIDGET_GTK
     70  mDisableHwCompositingNoWr = true;
     71 #endif
     72 
     73 #ifdef NIGHTLY_BUILD
     74  mIsNightly = true;
     75 #endif
     76 #ifdef EARLY_BETA_OR_EARLIER
     77  mIsEarlyBetaOrEarlier = true;
     78 #endif
     79  mSafeMode = gfxPlatform::InSafeMode();
     80 
     81  mGfxInfo = components::GfxInfo::Service();
     82 
     83  mFeatureWr = &gfxConfig::GetFeature(Feature::WEBRENDER);
     84  mFeatureWrCompositor = &gfxConfig::GetFeature(Feature::WEBRENDER_COMPOSITOR);
     85  mFeatureWrAngle = &gfxConfig::GetFeature(Feature::WEBRENDER_ANGLE);
     86  mFeatureWrDComp = &gfxConfig::GetFeature(Feature::WEBRENDER_DCOMP_PRESENT);
     87  mFeatureWrPartial = &gfxConfig::GetFeature(Feature::WEBRENDER_PARTIAL);
     88  mFeatureWrShaderCache =
     89      &gfxConfig::GetFeature(Feature::WEBRENDER_SHADER_CACHE);
     90  mFeatureWrOptimizedShaders =
     91      &gfxConfig::GetFeature(Feature::WEBRENDER_OPTIMIZED_SHADERS);
     92  mFeatureWrScissoredCacheClears =
     93      &gfxConfig::GetFeature(Feature::WEBRENDER_SCISSORED_CACHE_CLEARS);
     94 
     95  mFeatureHwCompositing = &gfxConfig::GetFeature(Feature::HW_COMPOSITING);
     96 #ifdef XP_WIN
     97  mFeatureD3D11HwAngle = &gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
     98  mFeatureD3D11Compositing = &gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
     99 #endif
    100  mFeatureGPUProcess = &gfxConfig::GetFeature(Feature::GPU_PROCESS);
    101  mFeatureGLNorm16Textures =
    102      &gfxConfig::GetFeature(Feature::GL_NORM16_TEXTURES);
    103 }
    104 
    105 void gfxConfigManager::EmplaceUserPref(const char* aPrefName,
    106                                       Maybe<bool>& aValue) {
    107  if (Preferences::HasUserValue(aPrefName)) {
    108    aValue.emplace(Preferences::GetBool(aPrefName, false));
    109  }
    110 }
    111 
    112 void gfxConfigManager::ConfigureFromBlocklist(long aFeature,
    113                                              FeatureState* aFeatureState) {
    114  MOZ_ASSERT(aFeatureState);
    115 
    116  nsCString blockId;
    117  int32_t status;
    118  if (!NS_SUCCEEDED(mGfxInfo->GetFeatureStatus(aFeature, blockId, &status))) {
    119    aFeatureState->Disable(FeatureStatus::BlockedNoGfxInfo, "gfxInfo is broken",
    120                           "FEATURE_FAILURE_NO_GFX_INFO"_ns);
    121    return;
    122  }
    123 
    124  switch (status) {
    125    case nsIGfxInfo::FEATURE_STATUS_OK:
    126    case nsIGfxInfo::FEATURE_ALLOW_ALWAYS:
    127      break;
    128    case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED:
    129      MOZ_ASSERT_UNREACHABLE("Allowing only qualified, but needs experiment?");
    130      break;
    131    case nsIGfxInfo::FEATURE_DENIED:
    132      aFeatureState->Disable(FeatureStatus::Denied, "Not on allowlist",
    133                             blockId);
    134      break;
    135    default:
    136      aFeatureState->Disable(FeatureStatus::Blocklisted,
    137                             "Blocklisted by gfxInfo", blockId);
    138      break;
    139  }
    140 }
    141 
    142 void gfxConfigManager::ConfigureWebRender() {
    143  MOZ_ASSERT(XRE_IsParentProcess());
    144  MOZ_ASSERT(mFeatureWr);
    145  MOZ_ASSERT(mFeatureWrCompositor);
    146  MOZ_ASSERT(mFeatureWrAngle);
    147  MOZ_ASSERT(mFeatureWrDComp);
    148  MOZ_ASSERT(mFeatureWrPartial);
    149  MOZ_ASSERT(mFeatureWrShaderCache);
    150  MOZ_ASSERT(mFeatureWrOptimizedShaders);
    151  MOZ_ASSERT(mFeatureWrScissoredCacheClears);
    152  MOZ_ASSERT(mFeatureHwCompositing);
    153  MOZ_ASSERT(mFeatureGPUProcess);
    154  MOZ_ASSERT(mFeatureGLNorm16Textures);
    155 
    156  // Initialize WebRender native compositor usage
    157  mFeatureWrCompositor->SetDefaultFromPref("gfx.webrender.compositor", true,
    158                                           false, mWrCompositorEnabled);
    159 
    160  if (mWrCompositorForceEnabled) {
    161    mFeatureWrCompositor->UserForceEnable("Force enabled by pref");
    162  }
    163 
    164  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR,
    165                         mFeatureWrCompositor);
    166 
    167  // Disable native compositor when hardware stretching is not supported. It is
    168  // for avoiding a problem like Bug 1618370.
    169  // XXX Is there a better check for Bug 1618370?
    170  if (!mHwStretchingSupport.IsFullySupported() && mScaledResolution) {
    171    nsPrintfCString failureId(
    172        "FEATURE_FAILURE_NO_HARDWARE_STRETCHING_B%uW%uF%uN%uE%u",
    173        mHwStretchingSupport.mBoth, mHwStretchingSupport.mWindowOnly,
    174        mHwStretchingSupport.mFullScreenOnly, mHwStretchingSupport.mNone,
    175        mHwStretchingSupport.mError);
    176    mFeatureWrCompositor->Disable(FeatureStatus::Unavailable,
    177                                  "No hardware stretching support", failureId);
    178  }
    179 
    180  mFeatureWr->EnableByDefault();
    181 
    182  // envvar works everywhere; note that we need this for testing in CI.
    183  // Prior to bug 1523788, the `prefEnabled` check was only done on Nightly,
    184  // so as to prevent random users from easily enabling WebRender on
    185  // unqualified hardware in beta/release.
    186  if (mWrSoftwareForceEnabled) {
    187    mFeatureWr->UserDisable("User force-enabled software WR",
    188                            "FEATURE_FAILURE_USER_FORCE_ENABLED_SW_WR"_ns);
    189  } else if (mWrEnvForceEnabled) {
    190    mFeatureWr->UserForceEnable("Force enabled by envvar");
    191  } else if (mWrForceEnabled) {
    192    mFeatureWr->UserForceEnable("Force enabled by pref");
    193  }
    194 
    195  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER, mFeatureWr);
    196 
    197  // HW_COMPOSITING being disabled implies interfacing with the GPU might break
    198  if (!mFeatureHwCompositing->IsEnabled()) {
    199    mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoHwCompositing,
    200                             "Hardware compositing is disabled",
    201                             "FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"_ns);
    202  }
    203 
    204  if (mSafeMode) {
    205    mFeatureWr->ForceDisable(FeatureStatus::UnavailableInSafeMode,
    206                             "Safe-mode is enabled",
    207                             "FEATURE_FAILURE_SAFE_MODE"_ns);
    208  }
    209 
    210  mFeatureWrAngle->EnableByDefault();
    211  if (mFeatureD3D11HwAngle) {
    212    if (mWrForceAngle) {
    213      if (!mFeatureD3D11HwAngle->IsEnabled()) {
    214        mFeatureWrAngle->ForceDisable(FeatureStatus::UnavailableNoAngle,
    215                                      "ANGLE is disabled",
    216                                      mFeatureD3D11HwAngle->GetFailureId());
    217      } else if (!mFeatureGPUProcess->IsEnabled() &&
    218                 !mWrForceAngleNoGPUProcess) {
    219        // WebRender with ANGLE relies on the GPU process when on Windows
    220        mFeatureWrAngle->ForceDisable(
    221            FeatureStatus::UnavailableNoGpuProcess, "GPU Process is disabled",
    222            "FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns);
    223      }
    224    } else {
    225      mFeatureWrAngle->Disable(FeatureStatus::Disabled, "ANGLE is not forced",
    226                               "FEATURE_FAILURE_ANGLE_NOT_FORCED"_ns);
    227    }
    228  } else {
    229    mFeatureWrAngle->Disable(FeatureStatus::Unavailable, "OS not supported",
    230                             "FEATURE_FAILURE_OS_NOT_SUPPORTED"_ns);
    231  }
    232 
    233  if (mWrForceAngle && mFeatureWr->IsEnabled() &&
    234      !mFeatureWrAngle->IsEnabled()) {
    235    // Ensure we disable WebRender if ANGLE is unavailable and it is required.
    236    mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoAngle,
    237                             "ANGLE is disabled",
    238                             mFeatureWrAngle->GetFailureId());
    239  }
    240 
    241  if (!mFeatureWr->IsEnabled() && mDisableHwCompositingNoWr) {
    242    if (mFeatureHwCompositing->IsEnabled()) {
    243      // Hardware compositing should be disabled by default if we aren't using
    244      // WebRender. We had to check if it is enabled at all, because it may
    245      // already have been forced disabled (e.g. safe mode, headless). It may
    246      // still be forced on by the user, and if so, this should have no effect.
    247      mFeatureHwCompositing->Disable(FeatureStatus::Blocked,
    248                                     "Acceleration blocked by platform", ""_ns);
    249    }
    250  }
    251 
    252  mFeatureWrDComp->EnableByDefault();
    253 
    254  if (!mWrDCompWinEnabled) {
    255    mFeatureWrDComp->UserDisable("User disabled via pref",
    256                                 "FEATURE_FAILURE_DCOMP_PREF_DISABLED"_ns);
    257  }
    258 
    259  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_DCOMP, mFeatureWrDComp);
    260 
    261  if (!mFeatureGPUProcess->IsEnabled()) {
    262    mFeatureWrDComp->Disable(FeatureStatus::Unavailable, "Requires GPU process",
    263                             "FEATURE_FAILURE_NO_GPU_PROCESS"_ns);
    264  }
    265 
    266  mFeatureWrDComp->MaybeSetFailed(
    267      mFeatureWr->IsEnabled(), FeatureStatus::Unavailable, "Requires WebRender",
    268      "FEATURE_FAILURE_DCOMP_NOT_WR"_ns);
    269  mFeatureWrDComp->MaybeSetFailed(mFeatureWrAngle->IsEnabled(),
    270                                  FeatureStatus::Unavailable, "Requires ANGLE",
    271                                  "FEATURE_FAILURE_DCOMP_NOT_ANGLE"_ns);
    272 
    273  if (!mFeatureWrDComp->IsEnabled() && mWrCompositorDCompRequired) {
    274    mFeatureWrCompositor->ForceDisable(FeatureStatus::Unavailable,
    275                                       "No DirectComposition usage",
    276                                       mFeatureWrDComp->GetFailureId());
    277  }
    278 
    279  // Initialize WebRender partial present config.
    280  // Partial present is used only when WebRender compositor is not used.
    281  mFeatureWrPartial->SetDefault(mWrPartialPresent, FeatureStatus::Disabled,
    282                                "User disabled via pref");
    283  if (mWrForcePartialPresent) {
    284    mFeatureWrPartial->UserForceEnable("Force enabled by pref");
    285  }
    286 
    287  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_PARTIAL_PRESENT,
    288                         mFeatureWrPartial);
    289 
    290  mFeatureWrShaderCache->SetDefaultFromPref(
    291      StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), true,
    292      StaticPrefs::GetPrefDefault_gfx_webrender_program_binary_disk(),
    293      mWrShaderCache);
    294  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SHADER_CACHE,
    295                         mFeatureWrShaderCache);
    296  if (!mFeatureWr->IsEnabled()) {
    297    mFeatureWrShaderCache->ForceDisable(FeatureStatus::Unavailable,
    298                                        "WebRender disabled",
    299                                        "FEATURE_FAILURE_WR_DISABLED"_ns);
    300  }
    301 
    302  mFeatureWrOptimizedShaders->EnableByDefault();
    303  if (!mWrOptimizedShaders) {
    304    mFeatureWrOptimizedShaders->UserDisable("User disabled via pref",
    305                                            "FEATURE_FAILURE_PREF_DISABLED"_ns);
    306  }
    307  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_OPTIMIZED_SHADERS,
    308                         mFeatureWrOptimizedShaders);
    309  if (!mFeatureWr->IsEnabled()) {
    310    mFeatureWrOptimizedShaders->ForceDisable(FeatureStatus::Unavailable,
    311                                             "WebRender disabled",
    312                                             "FEATURE_FAILURE_WR_DISABLED"_ns);
    313  }
    314 
    315  mFeatureWrScissoredCacheClears->SetDefault(mWrScissoredCacheClearsEnabled,
    316                                             FeatureStatus::Disabled,
    317                                             "User disabled via pref");
    318  if (mWrScissoredCacheClearsForceEnabled) {
    319    mFeatureWrScissoredCacheClears->UserForceEnable("Force enabled by pref");
    320  }
    321  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SCISSORED_CACHE_CLEARS,
    322                         mFeatureWrScissoredCacheClears);
    323 
    324  mFeatureGLNorm16Textures->EnableByDefault();
    325  ConfigureFromBlocklist(nsIGfxInfo::FEATURE_GL_NORM16_TEXTURES,
    326                         mFeatureGLNorm16Textures);
    327 }
    328 
    329 }  // namespace gfx
    330 }  // namespace mozilla