#include "gpu/ipc/service/gpu_init.h"
#include <cstdlib>
#include <cstring>
#include <optional>
#include <string>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "build/chromeos_buildflags.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/config/gpu_driver_bug_list.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_info_collector.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/config/gpu_switching.h"
#include "gpu/config/gpu_util.h"
#include "gpu/ipc/service/gpu_watchdog_thread.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/switches.h"
#include "ui/gl/buildflags.h"
#include "ui/gl/gl_display.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/init/gl_factory.h"
#if BUILDFLAG(IS_MAC)
#include <GLES2/gl2.h>
#endif
#if BUILDFLAG(IS_OZONE)
#include "gpu/vulkan/drm_modifiers_filter_vulkan.h"
#include "ui/ozone/public/drm_modifiers_filter.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "ui/gl/direct_composition_support.h"
#include "ui/gl/gl_surface_egl.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "ui/gfx/android/android_surface_control_compat.h"
#endif
#if BUILDFLAG(ENABLE_VULKAN)
#include "gpu/vulkan/init/vulkan_factory.h"
#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_instance.h"
#include "gpu/vulkan/vulkan_util.h"
#endif
#if !BUILDFLAG(IS_MAC)
#include "ui/gl/gl_fence_egl.h"
#endif
#if BUILDFLAG(USE_DAWN) || BUILDFLAG(SKIA_USE_DAWN)
#include "third_party/dawn/include/dawn/dawn_proc.h"
#include "third_party/dawn/include/dawn/native/DawnNative.h"
#endif
#if BUILDFLAG(SKIA_USE_DAWN)
#include "gpu/command_buffer/service/dawn_context_provider.h"
#include "third_party/dawn/include/dawn/webgpu_cpp.h"
#endif
#if BUILDFLAG(SKIA_USE_DAWN) && BUILDFLAG(IS_CHROMEOS)
#include "gpu/command_buffer/service/drm_modifiers_filter_dawn.h"
#endif
namespace gpu {
namespace {
bool CollectGraphicsInfo(GPUInfo* gpu_info) { … }
void InitializeDawnProcs() { … }
void InitializePlatformOverlaySettings(GPUInfo* gpu_info,
const GpuFeatureInfo& gpu_feature_info) { … }
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
bool CanAccessDeviceFile(const GPUInfo& gpu_info) { … }
#endif
class GpuWatchdogInit { … };
void PauseGpuWatchdog(GpuWatchdogThread* watchdog_thread) { … }
void ResumeGpuWatchdog(GpuWatchdogThread* watchdog_thread) { … }
void DisableInProcessGpuVulkan(GpuFeatureInfo* gpu_feature_info,
GpuPreferences* gpu_preferences) { … }
#if BUILDFLAG(IS_ANDROID)
void DisableInProcessGpuGraphite(GpuFeatureInfo& gpu_feature_info,
GpuPreferences& gpu_preferences) {
if (gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] ==
kGpuFeatureStatusEnabled ||
gpu_preferences.gr_context_type == GrContextType::kGraphiteDawn) {
LOG(ERROR) << "Graphite not supported with in process gpu";
gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] =
kGpuFeatureStatusDisabled;
gpu_preferences.gr_context_type = GrContextType::kGL;
}
}
#endif
#if BUILDFLAG(ENABLE_VULKAN)
bool MatchGLInfo(const std::string& field, const std::string& patterns) { … }
#endif
#if BUILDFLAG(IS_WIN)
uint64_t CHROME_LUID_to_uint64_t(const CHROME_LUID& luid) {
uint64_t id64 = static_cast<uint32_t>(luid.HighPart);
return (id64 << 32) | (luid.LowPart & 0xFFFFFFFF);
}
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
void SetupGLDisplayManagerEGL(const GPUInfo& gpu_info,
const GpuFeatureInfo& gpu_feature_info) {
const GPUInfo::GPUDevice* gpu_high_perf =
gpu_info.GetGpuByPreference(gl::GpuPreference::kHighPerformance);
const GPUInfo::GPUDevice* gpu_low_power =
gpu_info.GetGpuByPreference(gl::GpuPreference::kLowPower);
#if BUILDFLAG(IS_WIN)
const GPUInfo::GPUDevice* gpu_default = &(gpu_info.gpu);
uint64_t system_device_id_high_perf =
gpu_high_perf ? CHROME_LUID_to_uint64_t(gpu_high_perf->luid) : 0;
uint64_t system_device_id_low_power =
gpu_low_power ? CHROME_LUID_to_uint64_t(gpu_low_power->luid) : 0;
uint64_t system_device_id_default =
CHROME_LUID_to_uint64_t(gpu_default->luid);
#else
const GPUInfo::GPUDevice* gpu_default =
gpu_low_power ? gpu_low_power : &(gpu_info.gpu);
uint64_t system_device_id_high_perf =
gpu_high_perf ? gpu_high_perf->system_device_id : 0;
uint64_t system_device_id_low_power =
gpu_low_power ? gpu_low_power->system_device_id : 0;
uint64_t system_device_id_default = gpu_default->system_device_id;
#endif
DCHECK(gpu_default);
if (gpu_info.GpuCount() <= 1) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_default);
return;
}
if (gpu_feature_info.IsWorkaroundEnabled(FORCE_LOW_POWER_GPU) &&
system_device_id_low_power) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_low_power);
return;
}
if (gpu_feature_info.IsWorkaroundEnabled(FORCE_HIGH_PERFORMANCE_GPU) &&
system_device_id_high_perf) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_high_perf);
return;
}
if (gpu_default == gpu_high_perf) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_high_perf);
return;
}
gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
system_device_id_default);
if (system_device_id_high_perf) {
gl::SetGpuPreferenceEGL(gl::GpuPreference::kHighPerformance,
system_device_id_high_perf);
}
return;
}
#endif
}
GpuInit::GpuInit() = default;
GpuInit::~GpuInit() { … }
bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line,
const GpuPreferences& gpu_preferences) { … }
#if BUILDFLAG(IS_ANDROID)
void GpuInit::InitializeInProcess(base::CommandLine* command_line,
const GpuPreferences& gpu_preferences) {
gpu_preferences_ = gpu_preferences;
init_successful_ = true;
DCHECK(!EnableSwiftShaderIfNeeded(
command_line, gpu_feature_info_,
gpu_preferences_.disable_software_rasterizer, false));
gl::GLDisplay* gl_display = InitializeGLThreadSafe(
command_line, gpu_preferences_, &gpu_info_, &gpu_feature_info_);
if (!gl_display) {
LOG(FATAL) << "gpu::InitializeGLThreadSafe() failed.";
}
if (command_line->HasSwitch(switches::kWebViewDrawFunctorUsesVulkan)) {
bool result = InitializeVulkan();
CHECK(result);
} else {
DisableInProcessGpuVulkan(&gpu_feature_info_, &gpu_preferences_);
DisableInProcessGpuGraphite(gpu_feature_info_, gpu_preferences_);
}
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
InitializeDawnProcs();
}
#else
void GpuInit::InitializeInProcess(base::CommandLine* command_line,
const GpuPreferences& gpu_preferences) { … }
#endif
void GpuInit::SaveHardwareGpuInfoAndGpuFeatureInfo() { … }
void GpuInit::AdjustInfoToSwiftShader() { … }
scoped_refptr<gl::GLSurface> GpuInit::TakeDefaultOffscreenSurface() { … }
bool GpuInit::InitializeDawn() { … }
bool GpuInit::InitializeVulkan() { … }
}