Chromium源码由浅入深(四)
- 电脑硬件
- 2025-08-15 20:51:02

接前一篇文章: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_); }欲知后事如何,且看下回分解。
Chromium源码由浅入深(四)由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Chromium源码由浅入深(四)”