910e62b5创建于 1月15日历史提交
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_PRIVATE_H_
#define CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_PRIVATE_H_

#include <stddef.h>
#include <stdint.h>

#include <list>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/observer_list_threadsafe.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/common/content_export.h"
#include "media/base/supported_video_decoder_config.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/display/display_observer.h"
#include "ui/gl/gpu_preference.h"

namespace base {
class CommandLine;
}

namespace content {

class CONTENT_EXPORT GpuDataManagerImplPrivate {
 public:
  explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner);

  GpuDataManagerImplPrivate(const GpuDataManagerImplPrivate&) = delete;
  GpuDataManagerImplPrivate& operator=(const GpuDataManagerImplPrivate&) =
      delete;

  virtual ~GpuDataManagerImplPrivate();

  void StartUmaTimer();
  gpu::GPUInfo GetGPUInfo() const;
  gpu::GPUInfo GetGPUInfoForHardwareGpu() const;
  std::vector<std::string> GetDawnInfoList() const;
  bool GpuAccessAllowed(std::string* reason) const;
  bool GpuAccessAllowedForHardwareGpu(std::string* reason) const;
  void RequestDx12VulkanVideoGpuInfoIfNeeded(
      GpuDataManagerImpl::GpuInfoRequest request,
      bool delayed);
  bool IsEssentialGpuInfoAvailable() const;
  bool IsDx12VulkanVersionAvailable() const;
  bool IsGpuFeatureInfoAvailable() const;
  gpu::GpuFeatureStatus GetFeatureStatus(gpu::GpuFeatureType feature) const;
  void RequestVideoMemoryUsageStatsUpdate(
      GpuDataManager::VideoMemoryUsageStatsCallback callback) const;
  void AddObserver(GpuDataManagerObserver* observer);
  void RemoveObserver(GpuDataManagerObserver* observer);
  void UnblockDomainFrom3DAPIs(const GURL& url);
  void DisableHardwareAcceleration();
  bool HardwareAccelerationEnabled() const;
  bool IsGpuRasterizationForUIEnabled() const;

  void UpdateGpuInfo(
      const gpu::GPUInfo& gpu_info,
      const std::optional<gpu::GPUInfo>& optional_gpu_info_for_hardware_gpu);
#if BUILDFLAG(IS_WIN)
  void UpdateDirectXInfo(uint32_t d3d12_feature_level,
                         uint32_t directml_feature_level);
  void UpdateVulkanInfo(uint32_t vulkan_version);
  void UpdateDevicePerfInfo(const gpu::DevicePerfInfo& device_perf_info);

  void UpdateOverlayInfo(const gpu::OverlayInfo& overlay_info);
  void UpdateDXGIInfo(gfx::mojom::DXGIInfoPtr dxgi_info);
  void UpdateDirectXRequestStatus(bool request_continues);
  void UpdateVulkanRequestStatus(bool request_continues);
  bool DirectXRequested() const;
  bool VulkanRequested() const;
  void TerminateInfoCollectionGpuProcess();
#endif
  void PostCreateThreads();
  void UpdateDawnInfo(const std::vector<std::string>& dawn_info_list);

  void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info,
                            const std::optional<gpu::GpuFeatureInfo>&
                                gpu_feature_info_for_hardware_gpu);
  void UpdateGpuExtraInfo(const gfx::GpuExtraInfo& process_info);
  void UpdateMojoMediaVideoDecoderCapabilities(
      const media::SupportedVideoDecoderConfigs& configs);
  void UpdateMojoMediaVideoEncoderCapabilities(
      const media::VideoEncodeAccelerator::SupportedProfiles&
          supported_profiles);

  gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
  gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const;
  gfx::GpuExtraInfo GetGpuExtraInfo() const;

  bool IsGpuCompositingDisabled() const;
  bool IsGpuCompositingDisabledForHardwareGpu() const;

  void SetGpuCompositingDisabled();

  void AppendGpuCommandLine(base::CommandLine* command_line,
                            GpuProcessKind kind) const;

  void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences,
                            GpuProcessKind kind) const;

  void AddLogMessage(int level,
                     const std::string& header,
                     const std::string& message);

  void ProcessCrashed();

  base::Value::List GetLogMessages() const;

  void HandleGpuSwitch();

  void BlockDomainsFrom3DAPIs(const std::set<GURL>& urls,
                              gpu::DomainGuilt guilt);
  bool Are3DAPIsBlocked(const GURL& top_origin_url,
                        ThreeDAPIType requester);

  void Notify3DAPIBlocked(const GURL& top_origin_url,
                          int render_process_id,
                          int render_frame_id,
                          ThreeDAPIType requester);

  gpu::GpuMode GetGpuMode() const;
  void FallBackToNextGpuMode();
  void FallBackToNextGpuModeDueToCrash();

  bool CanFallback() const { return !fallback_modes_.empty(); }

  bool IsGpuProcessUsingHardwareGpu() const;

  void SetApplicationVisible(bool is_visible);

  void OnDisplayAdded(const display::Display& new_display);
  void OnDisplaysRemoved(const display::Displays& removed_displays);
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t changed_metrics);

#if BUILDFLAG(IS_LINUX)
  bool IsGpuMemoryBufferNV12Supported();
#endif  // BUILDFLAG(IS_LINUX)

  void DisableDomainBlockingFor3DAPIsForTesting();
  void BlocklistWebGLForTesting();
  void SetSkiaGraphiteEnabledForTesting(bool enabled);

 private:
  friend class GpuDataManagerImplPrivateTest;
  friend class GpuDataManagerImplPrivateTestP;

  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
                           GpuInfoUpdate);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           SingleContextLossDoesNotBlockDomain);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           TwoContextLossesBlockDomain);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           TwoSimultaneousContextLossesDoNotBlockDomain);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP, DomainBlockExpires);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP, UnblockDomain);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           Domain1DoesNotBlockDomain2);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           UnblockingDomain1DoesNotUnblockDomain2);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           SimultaneousContextLossDoesNotBlock);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           MultipleTDRsBlockAll);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP, MultipleTDRsExpire);
  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTestP,
                           MultipleTDRsCanBeUnblocked);

  // Indicates the reason that access to a given client API (like
  // WebGL) was blocked or not. This state is distinct from blocklisting of an
  // entire feature.
  enum class DomainBlockStatus {
    kBlocked,
    kAllDomainsBlocked,
    kNotBlocked,
  };

  using GpuDataManagerObserverList =
      base::ObserverListThreadSafe<GpuDataManagerObserver>;

  struct LogMessage {
    int level;
    std::string header;
    std::string message;

    LogMessage(int _level,
               const std::string& _header,
               const std::string& _message)
        : level(_level),
          header(_header),
          message(_message) { }
  };

  // GPUInfo related data that should stay the same value even after GPUInfo is
  // updated. After GPU process restart different GPUInfo can be sent back to
  // the browser so the values here will be used reset the fixed data.
  struct FixedGpuInfo {
    std::optional<bool> hardware_supports_vulkan;
  };

  // Decide the order of GPU process states, and go to the first one. This
  // should only be called once, during initialization.
  void InitializeGpuModes();

  // Called when GPU access (hardware acceleration and swiftshader) becomes
  // blocked.
  void OnGpuBlocked();

  // Helper to extract the domain from a given URL.
  std::string GetDomainFromURL(const GURL& url) const;

  // Implementation functions for blocking of 3D graphics APIs, used
  // for unit testing.
  void BlockDomainsFrom3DAPIsAtTime(const std::set<GURL>& url,
                                    gpu::DomainGuilt guilt,
                                    base::Time at_time);
  void ExpireOldBlockedDomainsAtTime(base::Time at_time) const;
  DomainBlockStatus Are3DAPIsBlockedAtTime(const GURL& url,
                                           base::Time at_time) const;
  base::TimeDelta GetDomainBlockingExpirationPeriod() const;

  // Notify all observers whenever there is a GPU info update.
  void NotifyGpuInfoUpdate();

  void RequestGpuSupportedDirectXVersion(bool delayed);
  void RequestGpuSupportedVulkanVersion(bool delayed);
  void RequestDawnInfo(bool delayed, bool collect_metrics);
  void RequestMojoMediaVideoCapabilities();

  void RecordCompositingMode();

  const raw_ptr<GpuDataManagerImpl> owner_;

  gpu::GpuFeatureInfo gpu_feature_info_;
  FixedGpuInfo fixed_gpu_info_;
  gpu::GPUInfo gpu_info_;
#if BUILDFLAG(IS_WIN)
  bool gpu_info_dx_valid_ = false;
  bool gpu_info_dx_requested_ = false;
  bool gpu_info_dx_request_failed_ = false;
  bool gpu_info_vulkan_valid_ = false;
  bool gpu_info_vulkan_requested_ = false;
  bool gpu_info_vulkan_request_failed_ = false;
#endif
  // The Dawn info queried from the GPU process.
  std::vector<std::string> dawn_info_list_;

  // What we would have gotten if we haven't fallen back to SwiftShader or
  // pure software (in the viz case).
  gpu::GpuFeatureInfo gpu_feature_info_for_hardware_gpu_;
  gpu::GPUInfo gpu_info_for_hardware_gpu_;
  bool is_gpu_compositing_disabled_for_hardware_gpu_ = false;
  bool gpu_access_allowed_for_hardware_gpu_ = true;
  std::string gpu_access_blocked_reason_for_hardware_gpu_;

  gfx::GpuExtraInfo gpu_extra_info_;

  const scoped_refptr<GpuDataManagerObserverList> observer_list_;

  // Periodically calls RecordCompositingMode() for compositing mode UMA.
  base::RepeatingTimer compositing_mode_timer_;

  // Contains the 1000 most recent log messages.
  std::vector<LogMessage> log_messages_;

  // What the gpu process is being run for.
  gpu::GpuMode gpu_mode_ = gpu::GpuMode::UNKNOWN;

  // Order of gpu process fallback states, used as a stack.
  std::vector<gpu::GpuMode> fallback_modes_;

  std::optional<display::ScopedOptionalDisplayObserver> display_observer_;

  // Used to tell if the gpu was disabled by an explicit call to
  // DisableHardwareAcceleration(), rather than by fallback.
  bool hardware_disabled_explicitly_ = false;

  // We disable histogram stuff in testing, especially in unit tests because
  // they cause random failures.
  bool update_histograms_ = true;

  struct DomainBlockingEntry {
    DomainBlockingEntry(const std::string& domain, gpu::DomainGuilt guilt)
        : domain(domain), guilt(guilt) {}

    std::string domain;
    gpu::DomainGuilt guilt;
  };

  // Implicitly sorted by increasing timestamp.
  mutable std::multimap<base::Time, DomainBlockingEntry> blocked_domains_;
  bool domain_blocking_enabled_ = true;

  bool application_is_visible_ = true;

  bool disable_gpu_compositing_ = false;
#if BUILDFLAG(IS_LINUX)
  bool is_gpu_memory_buffer_NV12_supported_ = false;
#endif  // BUILDFLAG(IS_LINUX)

  bool is_gpu_rasterization_for_ui_enabled_ = true;
};

}  // namespace content

#endif  // CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_PRIVATE_H_