当前位置: 首页 > news >正文

Chromium源码由浅入深(四)

接前一篇文章:Chromium源码由浅入深(三)

上回书结尾提到content/browser/gpu/gpu_internals_ui.cc的OnGpuInfoUpdate函数,本回对于这个函数的上下文进行深入分析。为了便于理解,再次贴出源码,如下:

void GpuMessageHandler::OnGpuInfoUpdate() {
  // Get GPU Info.
  const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
  const gfx::GpuExtraInfo gpu_extra_info =
      GpuDataManagerImpl::GetInstance()->GetGpuExtraInfo();
  base::Value::Dict gpu_info_val = GetGpuInfo();
 
  // Add in blocklisting features
  base::Value::Dict feature_status;
  feature_status.Set("featureStatus", GetFeatureStatus());
  feature_status.Set("problems", GetProblems());
  base::Value::List workarounds;
  for (const auto& workaround : GetDriverBugWorkarounds())
    workarounds.Append(workaround);
  feature_status.Set("workarounds", std::move(workarounds));
  gpu_info_val.Set("featureStatus", std::move(feature_status));
  if (!GpuDataManagerImpl::GetInstance()->IsGpuProcessUsingHardwareGpu()) {
    const gpu::GPUInfo gpu_info_for_hardware_gpu =
        GpuDataManagerImpl::GetInstance()->GetGPUInfoForHardwareGpu();
    if (gpu_info_for_hardware_gpu.IsInitialized()) {
      base::Value::Dict feature_status_for_hardware_gpu;
      feature_status_for_hardware_gpu.Set("featureStatus",
                                          GetFeatureStatusForHardwareGpu());
      feature_status_for_hardware_gpu.Set("problems",
                                          GetProblemsForHardwareGpu());
      base::Value::List workarounds_for_hardware_gpu;
      for (const auto& workaround : GetDriverBugWorkaroundsForHardwareGpu())
        workarounds_for_hardware_gpu.Append(workaround);
      feature_status_for_hardware_gpu.Set(
          "workarounds", std::move(workarounds_for_hardware_gpu));
      gpu_info_val.Set("featureStatusForHardwareGpu",
                       std::move(feature_status_for_hardware_gpu));
      const gpu::GpuFeatureInfo gpu_feature_info_for_hardware_gpu =
          GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfoForHardwareGpu();
      base::Value::List gpu_info_for_hardware_gpu_val = GetBasicGpuInfo(
          gpu_info_for_hardware_gpu, gpu_feature_info_for_hardware_gpu,
          gfx::GpuExtraInfo{});
      gpu_info_val.Set("basicInfoForHardwareGpu",
                       std::move(gpu_info_for_hardware_gpu_val));
    }
  }
  gpu_info_val.Set("compositorInfo", CompositorInfo());
  gpu_info_val.Set("gpuMemoryBufferInfo", GpuMemoryBufferInfo(gpu_extra_info));
  gpu_info_val.Set("displayInfo", GetDisplayInfo());
  gpu_info_val.Set("videoAcceleratorsInfo", GetVideoAcceleratorsInfo());
  gpu_info_val.Set("ANGLEFeatures", GetANGLEFeatures());
  gpu_info_val.Set("devicePerfInfo", GetDevicePerfInfo());
  gpu_info_val.Set("dawnInfo", GetDawnInfo());
 
  // Send GPU Info to javascript.
  web_ui()->CallJavascriptFunctionUnsafe("browserBridge.onGpuInfoUpdate",
                                         std::move(gpu_info_val));
}

重点关注以下代码片段:

 // Get GPU Info.
  const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
  const gfx::GpuExtraInfo gpu_extra_info =
      GpuDataManagerImpl::GetInstance()->GetGpuExtraInfo();
  base::Value::Dict gpu_info_val = GetGpuInfo();

先来分析第一句:

const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();

对应的函数在content/browser/gpu/gpu_data_manager_impl.cc中,代码如下:

gpu::GPUInfo GpuDataManagerImpl::GetGPUInfo() {
  base::AutoLock auto_lock(lock_);
  return private_->GetGPUInfo();
}

可见,该函数只是加了锁,实际的工作则是交给了private_->GetGPUInfo()。

private_是GpuDataManagerImpl类中的成员变量,其定义在content/browser/gpu/gpu_data_manager_impl.h中,如下:

 std::unique_ptr<GpuDataManagerImplPrivate> private_ GUARDED_BY(lock_)

也就是说private_->GetGPUInfo()实际调用的是GpuDataManagerImplPrivate类中的函数,在content/browser/gpu/gpu_data_manager_impl_private.h中,代码如下:

gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
  return gpu_info_;
}

这里只是得到gpu_info_的值,那么它是在哪里被设置(改变)的?

gpu_info_是GpuDataManagerImplPrivate类的成员变量,也是在content/browser/gpu/gpu_data_manager_impl_private.h中定义,如下:

  gpu::GPUInfo gpu_info_;

而对于gpu_info_的赋值则是在content/browser/gpu/gpu_data_manager_impl_private.cc的oid GpuDataManagerImplPrivate::UpdateGpuInfo函数(准确地说应该叫方法)中,代码如下:

void GpuDataManagerImplPrivate::UpdateGpuInfo(
    const gpu::GPUInfo& gpu_info,
    const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu) {
#if BUILDFLAG(IS_WIN)
  // If GPU process crashes and launches again, GPUInfo will be sent back from
  // the new GPU process again, and may overwrite the DX12, Vulkan, DxDiagNode
  // info we already collected. This is to make sure it doesn't happen.
  gpu::DxDiagNode dx_diagnostics = gpu_info_.dx_diagnostics;
  uint32_t d3d12_feature_level = gpu_info_.d3d12_feature_level;
  uint32_t vulkan_version = gpu_info_.vulkan_version;
#endif
  gpu_info_ = gpu_info;
  base::UmaHistogramCustomMicrosecondsTimes(
      "GPU.GPUInitializationTime.V3", gpu_info_.initialization_time,
      base::Milliseconds(5), base::Seconds(5), 50);
  UMA_HISTOGRAM_EXACT_LINEAR("GPU.GpuCount", gpu_info_.GpuCount(), 10);
  RecordDiscreteGpuHistograms(gpu_info_);
#if BUILDFLAG(IS_WIN)
  if (!dx_diagnostics.IsEmpty()) {
    gpu_info_.dx_diagnostics = dx_diagnostics;
  }
  if (d3d12_feature_level != 0) {
    gpu_info_.d3d12_feature_level = d3d12_feature_level;
  }
  if (vulkan_version != 0) {
    gpu_info_.vulkan_version = vulkan_version;
  }
#endif  // BUILDFLAG(IS_WIN)

  bool needs_to_update_gpu_info_for_hardware_gpu =
      !gpu_info_for_hardware_gpu_.IsInitialized();
  if (!needs_to_update_gpu_info_for_hardware_gpu &&
      !gpu_info_.UsesSwiftShader()) {
    // On multi-GPU system, when switching to a different GPU, we want to reset
    // GPUInfo for hardware GPU, because we want to know on which GPU Chrome
    // crashes multiple times and falls back to SwiftShader.
    const gpu::GPUInfo::GPUDevice& active_gpu = gpu_info_.active_gpu();
    const gpu::GPUInfo::GPUDevice& cached_active_gpu =
        gpu_info_for_hardware_gpu_.active_gpu();
#if BUILDFLAG(IS_WIN)
    if (active_gpu.luid.HighPart != cached_active_gpu.luid.HighPart &&
        active_gpu.luid.LowPart != cached_active_gpu.luid.LowPart) {
      needs_to_update_gpu_info_for_hardware_gpu = true;
    }
#else
    if (active_gpu.vendor_id != cached_active_gpu.vendor_id ||
        active_gpu.device_id != cached_active_gpu.device_id) {
      needs_to_update_gpu_info_for_hardware_gpu = true;
    }
#endif  // BUILDFLAG(IS_WIN)
  }

  if (needs_to_update_gpu_info_for_hardware_gpu) {
    if (gpu_info_for_hardware_gpu.has_value()) {
      DCHECK(gpu_info_for_hardware_gpu->IsInitialized());
      bool valid_info = true;
      if (gpu_info_for_hardware_gpu->UsesSwiftShader()) {
        valid_info = false;
      } else if (gpu_info_for_hardware_gpu->gl_renderer.empty() &&
                 gpu_info_for_hardware_gpu->active_gpu().vendor_id == 0u) {
        valid_info = false;
      }
      if (valid_info)
        gpu_info_for_hardware_gpu_ = gpu_info_for_hardware_gpu.value();
    } else {
      if (!gpu_info_.UsesSwiftShader())
        gpu_info_for_hardware_gpu_ = gpu_info_;
    }
  }

  GetContentClient()->SetGpuInfo(gpu_info_);
  NotifyGpuInfoUpdate();
}

那么又是在哪里调用的GpuDataManagerImplPrivate::UpdateGpuInfo()?

在Chromium源码中搜索,共有几处,而真正匹配的只有一处,在content/browser/gpu/gpu_data_manager_impl.cc中,代码如下:

void GpuDataManagerImpl::UpdateGpuInfo(
    const gpu::GPUInfo& gpu_info,
    const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu) {
  base::AutoLock auto_lock(lock_);
  private_->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
}

这就又回到了GpuDataManagerImpl类中。那么又是在哪里调用的GpuDataManagerImpl::UpdateGpuInfo()?

经过搜索定位,是在content/browser/gpu/gpu_process_host.cc中。但一共有两处都调用了这个函数。

  • 第一处 GpuProcessHost::DidInitialize()中调用

代码如下:

void GpuProcessHost::DidInitialize(
    const gpu::GPUInfo& gpu_info,
    const gpu::GpuFeatureInfo& gpu_feature_info,
    const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
    const absl::optional<gpu::GpuFeatureInfo>&
        gpu_feature_info_for_hardware_gpu,
    const gfx::GpuExtraInfo& gpu_extra_info) {
  if (GetGpuCrashCount() > 0) {
    LOG(WARNING) << "Reinitialized the GPU process after a crash. The reported "
                    "initialization time was "
                 << gpu_info.initialization_time.InMilliseconds() << " ms";
  }
  if (kind_ != GPU_PROCESS_KIND_INFO_COLLECTION) {
    auto* gpu_data_manager = GpuDataManagerImpl::GetInstance();
    // Update GpuFeatureInfo first, because UpdateGpuInfo() will notify all
    // listeners.
    gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info,
                                           gpu_feature_info_for_hardware_gpu);
    gpu_data_manager->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
    gpu_data_manager->UpdateGpuExtraInfo(gpu_extra_info);
  }

#if BUILDFLAG(IS_ANDROID)
  // Android may kill the GPU process to free memory, especially when the app
  // is the background, so Android cannot have a hard limit on GPU starts.
  // Reset crash count on Android when context creation succeeds, but only if no
  // fallback option is available.
  if (!GpuDataManagerImpl::GetInstance()->CanFallback())
    recent_crash_count_ = 0;
#endif
}
  • 第二处 GpuProcessHost::DidUpdateGPUInfo()中调用

代码如下:

void GpuProcessHost::DidUpdateGPUInfo(const gpu::GPUInfo& gpu_info) {
  GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info, absl::nullopt);
}

分别对以上两个函数(方法)进行搜索,搜索其被调用的地方,最终定位到实际上是在同一文件中,代码还挨着。是在components/viz/service/gl/gpu_service_impl.cc中,代码如下:

void GpuServiceImpl::UpdateGPUInfoGL() {
  DCHECK(main_runner_->BelongsToCurrentThread());
  gpu::CollectGraphicsInfoGL(&gpu_info_, GetContextState()->display());
  gpu_host_->DidUpdateGPUInfo(gpu_info_);
}

void GpuServiceImpl::InitializeWithHost(
    mojo::PendingRemote<mojom::GpuHost> pending_gpu_host,
    gpu::GpuProcessActivityFlags activity_flags,
    scoped_refptr<gl::GLSurface> default_offscreen_surface,
    gpu::SyncPointManager* sync_point_manager,
    gpu::SharedImageManager* shared_image_manager,
    gpu::Scheduler* scheduler,
    base::WaitableEvent* shutdown_event) {
  DCHECK(main_runner_->BelongsToCurrentThread());

  mojo::Remote<mojom::GpuHost> gpu_host(std::move(pending_gpu_host));
  gpu_host->DidInitialize(gpu_info_, gpu_feature_info_,
                          gpu_info_for_hardware_gpu_,
                          gpu_feature_info_for_hardware_gpu_, gpu_extra_info_);
  gpu_host_ = mojo::SharedRemote<mojom::GpuHost>(gpu_host.Unbind(), io_runner_);
  if (!in_host_process()) {
    // The global callback is reset from the dtor. So Unretained() here is safe.
    // Note that the callback can be called from any thread. Consequently, the
    // callback cannot use a WeakPtr.
    GetLogMessageManager()->InstallPostInitializeLogHandler(base::BindRepeating(
        &GpuServiceImpl::RecordLogMessage, base::Unretained(this)));
  }

  if (!sync_point_manager) {
    owned_sync_point_manager_ = std::make_unique<gpu::SyncPointManager>();
    sync_point_manager = owned_sync_point_manager_.get();
  }

  if (!shared_image_manager) {
    // When using real buffers for testing overlay configurations, we need
    // access to SharedImageManager on the viz thread to obtain the buffer
    // corresponding to a mailbox.
    const bool display_context_on_another_thread =
        features::IsDrDcEnabled() && !gpu_driver_bug_workarounds_.disable_drdc;
    bool thread_safe_manager = display_context_on_another_thread;
    // Raw draw needs to access shared image backing on the compositor thread.
    thread_safe_manager |= features::IsUsingRawDraw();
#if BUILDFLAG(IS_OZONE)
    thread_safe_manager |= features::ShouldUseRealBuffersForPageFlipTest();
#endif
    owned_shared_image_manager_ = std::make_unique<gpu::SharedImageManager>(
        thread_safe_manager, display_context_on_another_thread);
    shared_image_manager = owned_shared_image_manager_.get();
#if BUILDFLAG(IS_OZONE)
  } else {
    // With this feature enabled, we don't expect to receive an external
    // SharedImageManager.
    DCHECK(!features::ShouldUseRealBuffersForPageFlipTest());
#endif
  }

  shutdown_event_ = shutdown_event;
  if (!shutdown_event_) {
    owned_shutdown_event_ = std::make_unique<base::WaitableEvent>(
        base::WaitableEvent::ResetPolicy::MANUAL,
        base::WaitableEvent::InitialState::NOT_SIGNALED);
    shutdown_event_ = owned_shutdown_event_.get();
  }

  if (scheduler) {
    scheduler_ = scheduler;
  } else {
    owned_scheduler_ =
        std::make_unique<gpu::Scheduler>(sync_point_manager, gpu_preferences_);
    scheduler_ = owned_scheduler_.get();
  }

  // Defer creation of the render thread. This is to prevent it from handling
  // IPC messages before the sandbox has been enabled and all other necessary
  // initialization has succeeded.
  gpu_channel_manager_ = std::make_unique<gpu::GpuChannelManager>(
      gpu_preferences_, this, watchdog_thread_.get(), main_runner_, io_runner_,
      scheduler_, sync_point_manager, shared_image_manager,
      gpu_memory_buffer_factory_.get(), gpu_feature_info_,
      std::move(activity_flags), std::move(default_offscreen_surface),
      image_decode_accelerator_worker_.get(), vulkan_context_provider(),
      metal_context_provider_.get(), dawn_context_provider());

  media_gpu_channel_manager_ = std::make_unique<media::MediaGpuChannelManager>(
      gpu_channel_manager_.get());

  // Create and Initialize compositor gpu thread.
  compositor_gpu_thread_ = CompositorGpuThread::Create(
      gpu_channel_manager_.get(),
#if BUILDFLAG(ENABLE_VULKAN)
      vulkan_implementation_,
      vulkan_context_provider_ ? vulkan_context_provider_->GetDeviceQueue()
                               : nullptr,
#else
      nullptr, nullptr,
#endif
      gpu_channel_manager_->default_offscreen_surface()
          ? gpu_channel_manager_->default_offscreen_surface()->GetGLDisplay()
          : nullptr,
      !!watchdog_thread_);
}

欲知后事如何,且看下回分解。

相关文章:

  • python 裁剪图片并保存
  • 18、Python -- 函数入门与定义函数,多返回值函数和递归函数
  • 深度学习面试题目01
  • 每日一题 2520. 统计能整除数字的位数(简单)
  • Spring Security —漏洞防护—跨站请求伪造(CSRF)
  • MySQL数据库 #4
  • Spring MVC
  • 【Java 进阶篇】Java Servlet URL Patterns 详解
  • 高效集成|这一次,快人一步
  • 电脑怎么共享屏幕?电脑屏幕共享软件分享!
  • VB.NET 中使用SqlConnection类连接到Microsoft SQL Server数据库的详细步骤
  • Linux:firewalld防火墙-(实验2)-IP伪装与端口转发(4)
  • 用Python做数据分析之数据筛选及分类汇总
  • Python武器库开发-面向对象篇(六)
  • 数字驱动,营销赋能丨工商职院电子商务专业学生,前往餐饮美食电商新业态基地试岗交流
  • RunnerGo UI自动化使用流程
  • Spring Boot集成SpringFox 3.0与Pageable参数处理
  • C51--单片机中断
  • 025-第三代软件开发-实现需求长时间未操作返回登录界面
  • AUTOSAR汽车电子嵌入式编程精讲300篇-基于CAN总线的温度场测量装置的研究与设计
  • 习近平访问金砖国家新开发银行
  • 杨国荣︱学术上的立此存照——《故旧往事,欲说还休》读后
  • 对谈|李钧鹏、周忆粟:安德鲁·阿伯特过程社会学的魅力
  • 文化润疆|让新疆青少年成为“小小博物家”
  • 马上评丨机械停车库成“僵尸库”,设计不能闭门造车
  • 广州海关原党委委员、副关长刘小威被开除党籍