gpu_init.cc 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "gpu/ipc/service/gpu_init.h"
  5. #include <string>
  6. #include "base/base_paths.h"
  7. #include "base/command_line.h"
  8. #include "base/files/file_path.h"
  9. #include "base/logging.h"
  10. #include "base/metrics/field_trial_params.h"
  11. #include "base/metrics/histogram_macros.h"
  12. #include "base/path_service.h"
  13. #include "base/strings/pattern.h"
  14. #include "base/strings/string_number_conversions.h"
  15. #include "base/strings/string_split.h"
  16. #include "base/threading/scoped_blocking_call.h"
  17. #include "base/timer/elapsed_timer.h"
  18. #include "base/trace_event/trace_event.h"
  19. #include "build/build_config.h"
  20. #include "build/chromecast_buildflags.h"
  21. #include "build/chromeos_buildflags.h"
  22. #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
  23. #include "gpu/command_buffer/service/gpu_switches.h"
  24. #include "gpu/command_buffer/service/service_utils.h"
  25. #include "gpu/config/gpu_driver_bug_list.h"
  26. #include "gpu/config/gpu_driver_bug_workaround_type.h"
  27. #include "gpu/config/gpu_finch_features.h"
  28. #include "gpu/config/gpu_info_collector.h"
  29. #include "gpu/config/gpu_switches.h"
  30. #include "gpu/config/gpu_switching.h"
  31. #include "gpu/config/gpu_util.h"
  32. #include "gpu/ipc/service/gpu_watchdog_thread.h"
  33. #include "third_party/abseil-cpp/absl/types/optional.h"
  34. #include "ui/base/ui_base_features.h"
  35. #include "ui/gfx/switches.h"
  36. #include "ui/gl/buildflags.h"
  37. #include "ui/gl/gl_display.h"
  38. #include "ui/gl/gl_implementation.h"
  39. #include "ui/gl/gl_surface.h"
  40. #include "ui/gl/gl_switches.h"
  41. #include "ui/gl/gl_utils.h"
  42. #include "ui/gl/init/gl_factory.h"
  43. #if BUILDFLAG(IS_MAC)
  44. #include <GLES2/gl2.h>
  45. #endif
  46. #if defined(USE_OZONE)
  47. #include "ui/ozone/public/ozone_platform.h"
  48. #include "ui/ozone/public/surface_factory_ozone.h"
  49. #endif
  50. #if BUILDFLAG(IS_WIN)
  51. #include "gpu/config/gpu_driver_bug_workarounds.h"
  52. #include "ui/gl/direct_composition_support.h"
  53. #include "ui/gl/gl_surface_egl.h"
  54. #endif
  55. #if BUILDFLAG(IS_ANDROID)
  56. #include "base/android/android_image_reader_compat.h"
  57. #include "ui/gfx/android/android_surface_control_compat.h"
  58. #endif
  59. #if BUILDFLAG(ENABLE_VULKAN)
  60. #include "gpu/vulkan/init/vulkan_factory.h"
  61. #include "gpu/vulkan/vulkan_implementation.h"
  62. #include "gpu/vulkan/vulkan_instance.h"
  63. #include "gpu/vulkan/vulkan_util.h"
  64. #endif
  65. #if defined(USE_EGL) && !BUILDFLAG(IS_MAC)
  66. #include "ui/gl/gl_fence_egl.h"
  67. #endif
  68. namespace gpu {
  69. namespace {
  70. bool CollectGraphicsInfo(GPUInfo* gpu_info) {
  71. DCHECK(gpu_info);
  72. TRACE_EVENT0("gpu,startup", "Collect Graphics Info");
  73. bool success = CollectContextGraphicsInfo(gpu_info);
  74. if (!success)
  75. LOG(ERROR) << "CollectGraphicsInfo failed.";
  76. return success;
  77. }
  78. void InitializePlatformOverlaySettings(GPUInfo* gpu_info,
  79. const GpuFeatureInfo& gpu_feature_info) {
  80. #if BUILDFLAG(IS_WIN)
  81. // This has to be called after a context is created, active GPU is identified,
  82. // and GPU driver bug workarounds are computed again. Otherwise the workaround
  83. // |disable_direct_composition| may not be correctly applied.
  84. // Also, this has to be called after falling back to SwiftShader decision is
  85. // finalized because this function depends on GL is ANGLE's GLES or not.
  86. gl::DirectCompositionOverlayWorkarounds workarounds = {
  87. .enable_bgra8_overlays_with_yuv_overlay_support =
  88. gpu_feature_info.IsWorkaroundEnabled(
  89. gpu::ENABLE_BGRA8_OVERLAYS_WITH_YUV_OVERLAY_SUPPORT),
  90. .force_nv12_overlay_support =
  91. gpu_feature_info.IsWorkaroundEnabled(gpu::FORCE_NV12_OVERLAY_SUPPORT),
  92. .force_rgb10a2_overlay_support = gpu_feature_info.IsWorkaroundEnabled(
  93. gpu::FORCE_RGB10A2_OVERLAY_SUPPORT_FLAGS),
  94. .check_ycbcr_studio_g22_left_p709_for_nv12_support =
  95. gpu_feature_info.IsWorkaroundEnabled(
  96. gpu::CHECK_YCBCR_STUDIO_G22_LEFT_P709_FOR_NV12_SUPPORT)};
  97. SetDirectCompositionOverlayWorkarounds(workarounds);
  98. DCHECK(gpu_info);
  99. CollectHardwareOverlayInfo(&gpu_info->overlay_info);
  100. #elif BUILDFLAG(IS_ANDROID)
  101. if (gpu_info->gpu.vendor_string == "Qualcomm")
  102. gfx::SurfaceControl::EnableQualcommUBWC();
  103. #endif
  104. }
  105. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
  106. bool CanAccessDeviceFile(const GPUInfo& gpu_info) {
  107. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  108. if (gpu_info.gpu.vendor_id != 0x10de || // NVIDIA
  109. gpu_info.gpu.driver_vendor != "NVIDIA")
  110. return true;
  111. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  112. base::BlockingType::WILL_BLOCK);
  113. if (access("/dev/nvidiactl", R_OK) != 0) {
  114. DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied";
  115. return false;
  116. }
  117. return true;
  118. #else
  119. return true;
  120. #endif
  121. }
  122. #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
  123. class GpuWatchdogInit {
  124. public:
  125. GpuWatchdogInit() = default;
  126. ~GpuWatchdogInit() {
  127. if (watchdog_ptr_)
  128. watchdog_ptr_->OnInitComplete();
  129. }
  130. void SetGpuWatchdogPtr(GpuWatchdogThread* ptr) { watchdog_ptr_ = ptr; }
  131. private:
  132. GpuWatchdogThread* watchdog_ptr_ = nullptr;
  133. };
  134. // TODO(https://crbug.com/1095744): We currently do not handle
  135. // VK_ERROR_DEVICE_LOST in in-process-gpu.
  136. // Android WebView is allowed for now because it CHECKs on context loss.
  137. void DisableInProcessGpuVulkan(GpuFeatureInfo* gpu_feature_info,
  138. GpuPreferences* gpu_preferences) {
  139. if (gpu_feature_info->status_values[GPU_FEATURE_TYPE_VULKAN] ==
  140. kGpuFeatureStatusEnabled ||
  141. gpu_preferences->gr_context_type == GrContextType::kVulkan) {
  142. LOG(ERROR) << "Vulkan not supported with in process gpu";
  143. gpu_preferences->use_vulkan = VulkanImplementationName::kNone;
  144. gpu_feature_info->status_values[GPU_FEATURE_TYPE_VULKAN] =
  145. kGpuFeatureStatusDisabled;
  146. gpu_preferences->gr_context_type = GrContextType::kGL;
  147. }
  148. }
  149. #if BUILDFLAG(ENABLE_VULKAN)
  150. bool MatchGLInfo(const std::string& field, const std::string& patterns) {
  151. auto pattern_strings = base::SplitString(patterns, "|", base::TRIM_WHITESPACE,
  152. base::SPLIT_WANT_ALL);
  153. for (const auto& pattern : pattern_strings) {
  154. if (base::MatchPattern(field, pattern))
  155. return true;
  156. }
  157. return false;
  158. }
  159. #endif // BUILDFLAG(ENABLE_VULKAN)
  160. #if BUILDFLAG(IS_WIN)
  161. uint64_t CHROME_LUID_to_uint64_t(const CHROME_LUID& luid) {
  162. uint64_t id64 = static_cast<uint32_t>(luid.HighPart);
  163. return (id64 << 32) | (luid.LowPart & 0xFFFFFFFF);
  164. }
  165. #endif // BUILDFLAG(IS_WIN)
  166. #if defined(USE_EGL) && (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
  167. // GPU picking is only effective with ANGLE/Metal backend on Mac and
  168. // on Windows with EGL.
  169. // Returns the default GPU's system_device_id.
  170. uint64_t SetupGLDisplayManagerEGL(const GPUInfo& gpu_info,
  171. const GpuFeatureInfo& gpu_feature_info) {
  172. const GPUInfo::GPUDevice* gpu_high_perf =
  173. gpu_info.GetGpuByPreference(gl::GpuPreference::kHighPerformance);
  174. const GPUInfo::GPUDevice* gpu_low_power =
  175. gpu_info.GetGpuByPreference(gl::GpuPreference::kLowPower);
  176. #if BUILDFLAG(IS_WIN)
  177. // On Windows the default GPU may not be the low power GPU.
  178. const GPUInfo::GPUDevice* gpu_default = &(gpu_info.gpu);
  179. uint64_t system_device_id_high_perf =
  180. gpu_high_perf ? CHROME_LUID_to_uint64_t(gpu_high_perf->luid) : 0;
  181. uint64_t system_device_id_low_power =
  182. gpu_low_power ? CHROME_LUID_to_uint64_t(gpu_low_power->luid) : 0;
  183. uint64_t system_device_id_default =
  184. CHROME_LUID_to_uint64_t(gpu_default->luid);
  185. #else // IS_MAC
  186. const GPUInfo::GPUDevice* gpu_default =
  187. gpu_low_power ? gpu_low_power : &(gpu_info.gpu);
  188. uint64_t system_device_id_high_perf =
  189. gpu_high_perf ? gpu_high_perf->register_id : 0;
  190. uint64_t system_device_id_low_power =
  191. gpu_low_power ? gpu_low_power->register_id : 0;
  192. uint64_t system_device_id_default = gpu_default->register_id;
  193. #endif
  194. DCHECK(gpu_default);
  195. if (gpu_info.GpuCount() <= 1) {
  196. gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
  197. system_device_id_default);
  198. return system_device_id_default;
  199. }
  200. if (gpu_feature_info.IsWorkaroundEnabled(FORCE_LOW_POWER_GPU) &&
  201. system_device_id_low_power) {
  202. gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
  203. system_device_id_low_power);
  204. return system_device_id_low_power;
  205. }
  206. if (gpu_feature_info.IsWorkaroundEnabled(FORCE_HIGH_PERFORMANCE_GPU) &&
  207. system_device_id_high_perf) {
  208. gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
  209. system_device_id_high_perf);
  210. return system_device_id_high_perf;
  211. }
  212. if (gpu_default == gpu_high_perf) {
  213. // If the default GPU is already the high performance GPU, then it's better
  214. // for Chrome to always use this GPU.
  215. gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
  216. system_device_id_high_perf);
  217. return system_device_id_high_perf;
  218. }
  219. // Chrome uses the default GPU for internal rendering and the high
  220. // performance GPU for WebGL/WebGPU contexts that prefer high performance.
  221. // At this moment, a low power GPU different from the default GPU is not
  222. // supported.
  223. gl::SetGpuPreferenceEGL(gl::GpuPreference::kDefault,
  224. system_device_id_default);
  225. if (system_device_id_high_perf && features::SupportsEGLDualGpuRendering()) {
  226. gl::SetGpuPreferenceEGL(gl::GpuPreference::kHighPerformance,
  227. system_device_id_high_perf);
  228. }
  229. return system_device_id_default;
  230. }
  231. #endif // USE_EGL && (IS_WIN || IS_MAC)
  232. } // namespace
  233. GpuInit::GpuInit() = default;
  234. GpuInit::~GpuInit() {
  235. StopForceDiscreteGPU();
  236. }
  237. bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line,
  238. const GpuPreferences& gpu_preferences) {
  239. gpu_preferences_ = gpu_preferences;
  240. // Blocklist decisions based on basic GPUInfo may not be final. It might
  241. // need more context based GPUInfo. In such situations, switching to
  242. // SwiftShader needs to wait until creating a context.
  243. bool needs_more_info = true;
  244. uint64_t system_device_id = 0;
  245. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
  246. needs_more_info = false;
  247. if (!PopGPUInfoCache(&gpu_info_)) {
  248. CollectBasicGraphicsInfo(command_line, &gpu_info_);
  249. }
  250. IntelGpuSeriesType intel_gpu_series_type = GetIntelGpuSeriesType(
  251. gpu_info_.active_gpu().vendor_id, gpu_info_.active_gpu().device_id);
  252. UMA_HISTOGRAM_ENUMERATION("GPU.IntelGpuSeriesType", intel_gpu_series_type);
  253. // Set keys for crash logging based on preliminary gpu info, in case we
  254. // crash during feature collection.
  255. SetKeysForCrashLogging(gpu_info_);
  256. #if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
  257. gpu_info_.subpixel_font_rendering = false;
  258. #else
  259. gpu_info_.subpixel_font_rendering = true;
  260. #endif
  261. if (gpu_preferences_.enable_perf_data_collection) {
  262. // This is only enabled on the info collection GPU process.
  263. DevicePerfInfo device_perf_info;
  264. CollectDevicePerfInfo(&device_perf_info, /*in_browser_process=*/false);
  265. device_perf_info_ = device_perf_info;
  266. }
  267. if (!CanAccessDeviceFile(gpu_info_))
  268. return false;
  269. // GpuFeatureInfo is cached for the GPU service thread with WebView.
  270. if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) {
  271. // Compute blocklist and driver bug workaround decisions based on basic GPU
  272. // info.
  273. gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
  274. command_line, &needs_more_info);
  275. }
  276. #if defined(USE_EGL) && (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
  277. system_device_id = SetupGLDisplayManagerEGL(gpu_info_, gpu_feature_info_);
  278. #endif // USE_EGL && (IS_WIN || IS_MAC)
  279. #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CASTOS)
  280. gpu_info_.in_process_gpu = false;
  281. gl_use_swiftshader_ = false;
  282. // GL bindings may have already been initialized, specifically on MacOSX.
  283. bool gl_initialized = gl::GetGLImplementation() != gl::kGLImplementationNone;
  284. if (!gl_initialized) {
  285. // If GL has already been initialized, then it's too late to select GPU.
  286. if (SwitchableGPUsSupported(gpu_info_, *command_line)) {
  287. InitializeSwitchableGPUs(
  288. gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
  289. }
  290. } else {
  291. // If SwiftShader/SwANGLE is in use, set the flag gl_use_swiftshader_ so GPU
  292. // initialization will take a software rendering path. Do not do this if
  293. // SwiftShader/SwANGLE are explicitly requested via flags, because the flags
  294. // are meant to specify running SwiftShader/SwANGLE on the hardware GPU
  295. // path.
  296. gl::GLImplementationParts impl = gl::GetGLImplementationParts();
  297. bool fallback_to_software_gl = false;
  298. absl::optional<gl::GLImplementationParts> requested_impl =
  299. gl::GetRequestedGLImplementationFromCommandLine(
  300. command_line, &fallback_to_software_gl);
  301. if (gl::IsSoftwareGLImplementation(impl) &&
  302. !(requested_impl && gl::IsSoftwareGLImplementation(*requested_impl))) {
  303. gl_use_swiftshader_ = true;
  304. }
  305. }
  306. bool enable_watchdog = !gpu_preferences_.disable_gpu_watchdog &&
  307. !command_line->HasSwitch(switches::kHeadless) &&
  308. !gl_use_swiftshader_;
  309. // Disable the watchdog in debug builds because they tend to only be run by
  310. // developers who will not appreciate the watchdog killing the GPU process.
  311. #ifndef NDEBUG
  312. enable_watchdog = false;
  313. #endif
  314. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  315. bool gpu_sandbox_start_early = gpu_preferences_.gpu_sandbox_start_early;
  316. #else // !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
  317. // For some reasons MacOSX's VideoToolbox might crash when called after
  318. // initializing GL, see crbug.com/1047643 and crbug.com/871280. On other
  319. // operating systems like Windows and Android the pre-sandbox steps have
  320. // always been executed before initializing GL so keep it this way.
  321. bool gpu_sandbox_start_early = true;
  322. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  323. // PreSandbox is mainly for resource handling and not related to the GPU
  324. // driver, it doesn't need the GPU watchdog. The loadLibrary may take long
  325. // time that killing and restarting the GPU process will not help.
  326. if (gpu_sandbox_start_early) {
  327. // The sandbox will be started earlier than usual (i.e. before GL) so
  328. // execute the pre-sandbox steps now.
  329. sandbox_helper_->PreSandboxStartup(gpu_preferences);
  330. }
  331. // watchdog_init will call watchdog OnInitComplete() at the end of this
  332. // function.
  333. GpuWatchdogInit watchdog_init;
  334. // Don't start watchdog immediately, to allow developers to switch to VT2 on
  335. // startup.
  336. constexpr bool delayed_watchdog_enable = BUILDFLAG(IS_CHROMEOS_ASH);
  337. // Start the GPU watchdog only after anything that is expected to be time
  338. // consuming has completed, otherwise the process is liable to be aborted.
  339. if (enable_watchdog && !delayed_watchdog_enable) {
  340. watchdog_thread_ = GpuWatchdogThread::Create(
  341. gpu_preferences_.watchdog_starts_backgrounded, "GpuWatchdog");
  342. watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
  343. #if BUILDFLAG(IS_WIN)
  344. // This is a workaround for an occasional deadlock between watchdog and
  345. // current thread. Watchdog hangs at thread initialization in
  346. // __acrt_thread_attach() and current thread in std::setlocale(...)
  347. // (during InitializeGLOneOff()). Source of the deadlock looks like an old
  348. // UCRT bug that was supposed to be fixed in 10.0.10586 release of UCRT,
  349. // but we might have come accross a not-yet-covered scenario.
  350. // References:
  351. // https://bugs.python.org/issue26624
  352. // http://stackoverflow.com/questions/35572792/setlocale-stuck-on-windows
  353. bool watchdog_started = watchdog_thread_->WaitUntilThreadStarted();
  354. DCHECK(watchdog_started);
  355. #endif // BUILDFLAG(IS_WIN)
  356. }
  357. bool attempted_startsandbox = false;
  358. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  359. // On Chrome OS ARM Mali, GPU driver userspace creates threads when
  360. // initializing a GL context, so start the sandbox early.
  361. // TODO(zmo): Need to collect OS version before this.
  362. if (gpu_preferences_.gpu_sandbox_start_early) {
  363. gpu_info_.sandboxed = sandbox_helper_->EnsureSandboxInitialized(
  364. watchdog_thread_.get(), &gpu_info_, gpu_preferences_);
  365. attempted_startsandbox = true;
  366. }
  367. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  368. base::ElapsedTimer elapsed_timer;
  369. #if defined(USE_OZONE)
  370. // Initialize Ozone GPU after the watchdog in case it hangs. The sandbox
  371. // may also have started at this point.
  372. ui::OzonePlatform::InitParams params;
  373. params.single_process = false;
  374. params.enable_native_gpu_memory_buffers =
  375. gpu_preferences_.enable_native_gpu_memory_buffers;
  376. // Page flip testing will only happen in ash-chrome, not in lacros-chrome.
  377. // Therefore, we only allow or disallow sync and real buffer page flip
  378. // testing for ash-chrome.
  379. #if BUILDFLAG(IS_CHROMEOS_ASH)
  380. #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
  381. params.allow_sync_and_real_buffer_page_flip_testing =
  382. gpu_preferences_.enable_chromeos_direct_video_decoder;
  383. #else // !BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
  384. params.allow_sync_and_real_buffer_page_flip_testing = true;
  385. #endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
  386. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  387. ui::OzonePlatform::InitializeForGPU(params);
  388. // We need to get supported formats before sandboxing to avoid an known
  389. // issue which breaks the camera preview. (b/166850715)
  390. std::vector<gfx::BufferFormat> supported_buffer_formats_for_texturing =
  391. ui::OzonePlatform::GetInstance()
  392. ->GetSurfaceFactoryOzone()
  393. ->GetSupportedFormatsForTexturing();
  394. #endif // defined(USE_OZONE)
  395. if (!gl_use_swiftshader_) {
  396. gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
  397. command_line, gpu_feature_info_,
  398. gpu_preferences_.disable_software_rasterizer, needs_more_info);
  399. }
  400. if (gl_initialized && gl_use_swiftshader_ &&
  401. !gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) {
  402. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  403. VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
  404. << "on Linux";
  405. return false;
  406. #else // !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
  407. SaveHardwareGpuInfoAndGpuFeatureInfo();
  408. gl::init::ShutdownGL(nullptr, true);
  409. gl_initialized = false;
  410. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  411. }
  412. gl::GLDisplay* gl_display = nullptr;
  413. if (!gl_initialized) {
  414. // Pause watchdog. LoadLibrary in GLBindings may take long time.
  415. if (watchdog_thread_)
  416. watchdog_thread_->PauseWatchdog();
  417. gl_initialized = gl::init::InitializeStaticGLBindingsOneOff();
  418. if (!gl_initialized) {
  419. VLOG(1) << "gl::init::InitializeStaticGLBindingsOneOff failed";
  420. return false;
  421. }
  422. if (watchdog_thread_)
  423. watchdog_thread_->ResumeWatchdog();
  424. if (gl::GetGLImplementation() != gl::kGLImplementationDisabled) {
  425. gl_display = gl::init::InitializeGLNoExtensionsOneOff(
  426. /*init_bindings*/ false, system_device_id);
  427. gl_initialized = !!gl_display;
  428. if (!gl_initialized) {
  429. VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
  430. return false;
  431. }
  432. }
  433. }
  434. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  435. // The ContentSandboxHelper is currently the only one implementation of
  436. // GpuSandboxHelper and it has no dependency. Except on Linux where
  437. // VaapiWrapper checks the GL implementation to determine which display
  438. // to use. So call PreSandboxStartup after GL initialization. But make
  439. // sure the watchdog is paused as loadLibrary may take a long time and
  440. // restarting the GPU process will not help.
  441. if (!attempted_startsandbox) {
  442. if (watchdog_thread_)
  443. watchdog_thread_->PauseWatchdog();
  444. // The sandbox is not started yet.
  445. sandbox_helper_->PreSandboxStartup(gpu_preferences);
  446. if (watchdog_thread_)
  447. watchdog_thread_->ResumeWatchdog();
  448. }
  449. #endif
  450. auto impl = gl::GetGLImplementationParts();
  451. bool gl_disabled = impl == gl::kGLImplementationDisabled;
  452. bool is_swangle = impl == gl::ANGLEImplementation::kSwiftShader;
  453. // Compute passthrough decoder status before ComputeGpuFeatureInfo below.
  454. // Do this after GL is initialized so extensions can be queried.
  455. // Using SwANGLE forces the passthrough command decoder.
  456. if (gpu_preferences_.use_passthrough_cmd_decoder || is_swangle) {
  457. gpu_info_.passthrough_cmd_decoder =
  458. gles2::PassthroughCommandDecoderSupported();
  459. #if BUILDFLAG(IS_ANDROID)
  460. // We never use swiftshader on Android
  461. LOG_IF(DFATAL, !gpu_info_.passthrough_cmd_decoder)
  462. #else
  463. LOG_IF(ERROR, !gpu_info_.passthrough_cmd_decoder)
  464. #endif
  465. << "Passthrough is not supported, GL is "
  466. << gl::GetGLImplementationGLName(gl::GetGLImplementationParts())
  467. << ", ANGLE is "
  468. << gl::GetGLImplementationANGLEName(gl::GetGLImplementationParts());
  469. } else {
  470. gpu_info_.passthrough_cmd_decoder = false;
  471. }
  472. gpu_preferences_.use_passthrough_cmd_decoder =
  473. gpu_info_.passthrough_cmd_decoder;
  474. // We need to collect GL strings (VENDOR, RENDERER) for blocklisting purposes.
  475. if (!gl_disabled) {
  476. if (!gl_use_swiftshader_) {
  477. if (!CollectGraphicsInfo(&gpu_info_)) {
  478. VLOG(1) << "gpu::CollectGraphicsInfo failed";
  479. return false;
  480. }
  481. SetKeysForCrashLogging(gpu_info_);
  482. gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
  483. command_line, nullptr);
  484. gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
  485. command_line, gpu_feature_info_,
  486. gpu_preferences_.disable_software_rasterizer, false);
  487. if (gl_use_swiftshader_) {
  488. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  489. VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
  490. << "on Linux";
  491. return false;
  492. #else
  493. SaveHardwareGpuInfoAndGpuFeatureInfo();
  494. gl::init::ShutdownGL(gl_display, true);
  495. watchdog_thread_ = nullptr;
  496. watchdog_init.SetGpuWatchdogPtr(nullptr);
  497. gl_display = gl::init::InitializeGLNoExtensionsOneOff(
  498. /*init_bindings=*/true, system_device_id);
  499. if (!gl_display) {
  500. VLOG(1)
  501. << "gl::init::InitializeGLNoExtensionsOneOff with SwiftShader "
  502. << "failed";
  503. return false;
  504. }
  505. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  506. }
  507. } else { // gl_use_swiftshader_ == true
  508. switch (gpu_preferences_.use_vulkan) {
  509. case VulkanImplementationName::kNative: {
  510. // Collect GPU info, so we can use blocklist to disable vulkan if it
  511. // is needed.
  512. GPUInfo gpu_info;
  513. if (!CollectGraphicsInfo(&gpu_info)) {
  514. VLOG(1) << "gpu::CollectGraphicsInfo failed";
  515. return false;
  516. }
  517. auto gpu_feature_info = ComputeGpuFeatureInfo(
  518. gpu_info, gpu_preferences_, command_line, nullptr);
  519. gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
  520. gpu_feature_info.status_values[GPU_FEATURE_TYPE_VULKAN];
  521. break;
  522. }
  523. case VulkanImplementationName::kForcedNative:
  524. case VulkanImplementationName::kSwiftshader:
  525. gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
  526. kGpuFeatureStatusEnabled;
  527. break;
  528. case VulkanImplementationName::kNone:
  529. gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
  530. kGpuFeatureStatusDisabled;
  531. break;
  532. }
  533. }
  534. }
  535. // On MacOS, the default texture target for native GpuMemoryBuffers is
  536. // GL_TEXTURE_RECTANGLE_ARB. This is due to CGL's requirements for creating
  537. // a GL surface. However, when ANGLE is used on top of SwiftShader or Metal,
  538. // it's necessary to use GL_TEXTURE_2D instead.
  539. // TODO(crbug.com/1056312): The proper behavior is to check the config
  540. // parameter set by the EGL_ANGLE_iosurface_client_buffer extension
  541. #if BUILDFLAG(IS_MAC)
  542. if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE &&
  543. (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader ||
  544. gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal)) {
  545. SetMacOSSpecificTextureTarget(GL_TEXTURE_2D);
  546. gpu_info_.macos_specific_texture_target = GL_TEXTURE_2D;
  547. }
  548. #endif // BUILDFLAG(IS_MAC)
  549. #if BUILDFLAG(IS_WIN)
  550. {
  551. // On Windows, MITIGATION_FORCE_MS_SIGNED_BINS is used which disallows
  552. // loading any .dll that is not signed by Microsoft. Preload the SwiftShader
  553. // .dll so it may be accessed later. This is needed for WebGPU to
  554. // initialize a software fallback adapter.
  555. // Don't handle errors as failure here is non-fatal. Loading SwiftShader
  556. // again at a later point will fail as well.
  557. base::FilePath module_path;
  558. if (base::PathService::Get(base::DIR_MODULE, &module_path)) {
  559. base::LoadNativeLibrary(module_path.Append(L"vk_swiftshader.dll"),
  560. nullptr);
  561. }
  562. }
  563. #endif // BUILDFLAG(IS_WIN)
  564. if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] !=
  565. kGpuFeatureStatusEnabled ||
  566. !InitializeVulkan()) {
  567. gpu_preferences_.use_vulkan = VulkanImplementationName::kNone;
  568. gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
  569. kGpuFeatureStatusDisabled;
  570. if (gpu_preferences_.gr_context_type == GrContextType::kVulkan) {
  571. #if BUILDFLAG(IS_FUCHSIA)
  572. // Fuchsia uses ANGLE for GL which requires Vulkan, so don't fall
  573. // back to GL if Vulkan init fails.
  574. LOG(FATAL) << "Vulkan initialization failed";
  575. #endif
  576. gpu_preferences_.gr_context_type = GrContextType::kGL;
  577. }
  578. } else {
  579. // TODO(https://crbug.com/1095744): It would be better to cleanly tear
  580. // down and recreate the VkDevice on VK_ERROR_DEVICE_LOST. Until that
  581. // happens, we will exit_on_context_lost to ensure there are no leaks.
  582. gpu_feature_info_.enabled_gpu_driver_bug_workarounds.push_back(
  583. EXIT_ON_CONTEXT_LOST);
  584. }
  585. // Collect GPU process info
  586. if (!gl_disabled) {
  587. if (!CollectGpuExtraInfo(&gpu_extra_info_, gpu_preferences)) {
  588. VLOG(1) << "gpu::CollectGpuExtraInfo failed";
  589. return false;
  590. }
  591. }
  592. if (!gl_disabled) {
  593. if (!gpu_feature_info_.disabled_extensions.empty()) {
  594. gl::init::SetDisabledExtensionsPlatform(
  595. gpu_feature_info_.disabled_extensions);
  596. }
  597. if (!gl::init::InitializeExtensionSettingsOneOffPlatform(gl_display)) {
  598. VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
  599. return false;
  600. }
  601. default_offscreen_surface_ =
  602. gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
  603. if (!default_offscreen_surface_) {
  604. VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
  605. return false;
  606. }
  607. }
  608. InitializePlatformOverlaySettings(&gpu_info_, gpu_feature_info_);
  609. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  610. // Driver may create a compatibility profile context when collect graphics
  611. // information on Linux platform. Try to collect graphics information
  612. // based on core profile context after disabling platform extensions.
  613. if (!gl_disabled && !gl_use_swiftshader_) {
  614. if (!CollectGraphicsInfo(&gpu_info_))
  615. return false;
  616. SetKeysForCrashLogging(gpu_info_);
  617. gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
  618. command_line, nullptr);
  619. gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
  620. command_line, gpu_feature_info_,
  621. gpu_preferences_.disable_software_rasterizer, false);
  622. if (gl_use_swiftshader_) {
  623. VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
  624. << "on Linux";
  625. return false;
  626. }
  627. }
  628. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  629. if (gl_use_swiftshader_) {
  630. AdjustInfoToSwiftShader();
  631. }
  632. if (kGpuFeatureStatusEnabled !=
  633. gpu_feature_info_
  634. .status_values[GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE]) {
  635. gpu_preferences_.disable_accelerated_video_decode = true;
  636. }
  637. if (kGpuFeatureStatusEnabled !=
  638. gpu_feature_info_
  639. .status_values[GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE]) {
  640. gpu_preferences_.disable_accelerated_video_encode = true;
  641. }
  642. UMA_HISTOGRAM_MEDIUM_TIMES("GPU.InitializeOneOffMediumTime",
  643. elapsed_timer.Elapsed());
  644. // SwANGLE is expected to run slowly, so disable the watchdog
  645. // in that case.
  646. if (!gl_use_swiftshader_ && command_line->HasSwitch(switches::kUseGL)) {
  647. std::string use_gl = command_line->GetSwitchValueASCII(switches::kUseGL);
  648. std::string use_angle =
  649. command_line->GetSwitchValueASCII(switches::kUseANGLE);
  650. if (use_gl == gl::kGLImplementationANGLEName &&
  651. (use_angle == gl::kANGLEImplementationSwiftShaderName ||
  652. use_angle == gl::kANGLEImplementationSwiftShaderForWebGLName)) {
  653. gl_use_swiftshader_ = true;
  654. }
  655. }
  656. if (gl_use_swiftshader_ ||
  657. gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) {
  658. gpu_info_.software_rendering = true;
  659. watchdog_thread_ = nullptr;
  660. watchdog_init.SetGpuWatchdogPtr(nullptr);
  661. } else if (gl_disabled) {
  662. watchdog_thread_ = nullptr;
  663. watchdog_init.SetGpuWatchdogPtr(nullptr);
  664. } else if (enable_watchdog && delayed_watchdog_enable) {
  665. watchdog_thread_ = GpuWatchdogThread::Create(
  666. gpu_preferences_.watchdog_starts_backgrounded, "GpuWatchdog");
  667. watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
  668. }
  669. UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
  670. if (!gpu_info_.sandboxed && !attempted_startsandbox) {
  671. gpu_info_.sandboxed = sandbox_helper_->EnsureSandboxInitialized(
  672. watchdog_thread_.get(), &gpu_info_, gpu_preferences_);
  673. }
  674. UMA_HISTOGRAM_BOOLEAN("GPU.Sandbox.InitializedSuccessfully",
  675. gpu_info_.sandboxed);
  676. init_successful_ = true;
  677. #if defined(USE_OZONE)
  678. ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
  679. gpu_feature_info_.supported_buffer_formats_for_allocation_and_texturing =
  680. std::move(supported_buffer_formats_for_texturing);
  681. #endif
  682. if (!watchdog_thread_)
  683. watchdog_init.SetGpuWatchdogPtr(nullptr);
  684. #if BUILDFLAG(IS_WIN)
  685. if (gpu_feature_info_.IsWorkaroundEnabled(DISABLE_DECODE_SWAP_CHAIN))
  686. gl::DisableDirectCompositionDecodeSwapChain();
  687. if (gpu_feature_info_.IsWorkaroundEnabled(
  688. DISABLE_DIRECT_COMPOSITION_SW_VIDEO_OVERLAYS)) {
  689. gl::DisableDirectCompositionSoftwareOverlays();
  690. }
  691. #endif
  692. #if defined(USE_EGL) && !BUILDFLAG(IS_MAC)
  693. if (gpu_feature_info_.IsWorkaroundEnabled(CHECK_EGL_FENCE_BEFORE_WAIT))
  694. gl::GLFenceEGL::CheckEGLFenceBeforeWait();
  695. #endif
  696. return true;
  697. }
  698. #if BUILDFLAG(IS_ANDROID)
  699. void GpuInit::InitializeInProcess(base::CommandLine* command_line,
  700. const GpuPreferences& gpu_preferences) {
  701. gpu_preferences_ = gpu_preferences;
  702. init_successful_ = true;
  703. DCHECK(!EnableSwiftShaderIfNeeded(
  704. command_line, gpu_feature_info_,
  705. gpu_preferences_.disable_software_rasterizer, false));
  706. gl::GLDisplay* gl_display = InitializeGLThreadSafe(
  707. command_line, gpu_preferences_, &gpu_info_, &gpu_feature_info_);
  708. if (command_line->HasSwitch(switches::kWebViewDrawFunctorUsesVulkan) &&
  709. base::FeatureList::IsEnabled(features::kWebViewVulkan)) {
  710. bool result = InitializeVulkan();
  711. // There is no fallback for webview.
  712. CHECK(result);
  713. } else {
  714. DisableInProcessGpuVulkan(&gpu_feature_info_, &gpu_preferences_);
  715. }
  716. default_offscreen_surface_ =
  717. gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
  718. UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
  719. }
  720. #else
  721. void GpuInit::InitializeInProcess(base::CommandLine* command_line,
  722. const GpuPreferences& gpu_preferences) {
  723. gpu_preferences_ = gpu_preferences;
  724. init_successful_ = true;
  725. #if defined(USE_OZONE)
  726. ui::OzonePlatform::InitParams params;
  727. params.single_process = true;
  728. // Page flip testing will only happen in ash-chrome, not in lacros-chrome.
  729. // Therefore, we only allow or disallow sync and real buffer page flip
  730. // testing for ash-chrome.
  731. #if BUILDFLAG(IS_CHROMEOS_ASH)
  732. #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
  733. params.allow_sync_and_real_buffer_page_flip_testing =
  734. gpu_preferences_.enable_chromeos_direct_video_decoder;
  735. #else // !BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
  736. params.allow_sync_and_real_buffer_page_flip_testing = true;
  737. #endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
  738. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  739. ui::OzonePlatform::InitializeForGPU(params);
  740. #endif
  741. bool needs_more_info = true;
  742. #if !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
  743. needs_more_info = false;
  744. if (!PopGPUInfoCache(&gpu_info_)) {
  745. CollectBasicGraphicsInfo(command_line, &gpu_info_);
  746. }
  747. #if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
  748. gpu_info_.subpixel_font_rendering = false;
  749. #else
  750. gpu_info_.subpixel_font_rendering = true;
  751. #endif
  752. if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) {
  753. gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
  754. command_line, &needs_more_info);
  755. }
  756. if (SwitchableGPUsSupported(gpu_info_, *command_line)) {
  757. InitializeSwitchableGPUs(
  758. gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
  759. }
  760. #endif // !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
  761. gl::GLDisplay* gl_display = nullptr;
  762. gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
  763. command_line, gpu_feature_info_,
  764. gpu_preferences_.disable_software_rasterizer, needs_more_info);
  765. gl_display = gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings=*/true,
  766. /*system_device_id=*/0);
  767. if (!gl_display) {
  768. VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
  769. return;
  770. }
  771. bool gl_disabled = gl::GetGLImplementation() == gl::kGLImplementationDisabled;
  772. if (!gl_disabled && !gl_use_swiftshader_) {
  773. CollectContextGraphicsInfo(&gpu_info_);
  774. gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
  775. command_line, nullptr);
  776. gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
  777. command_line, gpu_feature_info_,
  778. gpu_preferences_.disable_software_rasterizer, false);
  779. if (gl_use_swiftshader_) {
  780. SaveHardwareGpuInfoAndGpuFeatureInfo();
  781. gl::init::ShutdownGL(gl_display, true);
  782. gl_display = gl::init::InitializeGLNoExtensionsOneOff(
  783. /*init_bindings=*/true, /*system_device_id=*/0);
  784. if (!gl_display) {
  785. VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
  786. << "with SwiftShader";
  787. return;
  788. }
  789. }
  790. }
  791. // On MacOS, the default texture target for native GpuMemoryBuffers is
  792. // GL_TEXTURE_RECTANGLE_ARB. This is due to CGL's requirements for creating
  793. // a GL surface. However, when ANGLE is used on top of SwiftShader or Metal,
  794. // it's necessary to use GL_TEXTURE_2D instead.
  795. // TODO(crbug.com/1056312): The proper behavior is to check the config
  796. // parameter set by the EGL_ANGLE_iosurface_client_buffer extension
  797. #if BUILDFLAG(IS_MAC)
  798. if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE &&
  799. (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader ||
  800. gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal)) {
  801. SetMacOSSpecificTextureTarget(GL_TEXTURE_2D);
  802. gpu_info_.macos_specific_texture_target = GL_TEXTURE_2D;
  803. }
  804. #endif // BUILDFLAG(IS_MAC)
  805. if (!gl_disabled) {
  806. if (!gpu_feature_info_.disabled_extensions.empty()) {
  807. gl::init::SetDisabledExtensionsPlatform(
  808. gpu_feature_info_.disabled_extensions);
  809. }
  810. if (!gl::init::InitializeExtensionSettingsOneOffPlatform(gl_display)) {
  811. VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
  812. }
  813. default_offscreen_surface_ =
  814. gl::init::CreateOffscreenGLSurface(gl_display, gfx::Size());
  815. if (!default_offscreen_surface_) {
  816. VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
  817. }
  818. }
  819. InitializePlatformOverlaySettings(&gpu_info_, gpu_feature_info_);
  820. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  821. // Driver may create a compatibility profile context when collect graphics
  822. // information on Linux platform. Try to collect graphics information
  823. // based on core profile context after disabling platform extensions.
  824. if (!gl_disabled && !gl_use_swiftshader_) {
  825. CollectContextGraphicsInfo(&gpu_info_);
  826. gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
  827. command_line, nullptr);
  828. gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
  829. command_line, gpu_feature_info_,
  830. gpu_preferences_.disable_software_rasterizer, false);
  831. if (gl_use_swiftshader_) {
  832. SaveHardwareGpuInfoAndGpuFeatureInfo();
  833. gl::init::ShutdownGL(gl_display, true);
  834. gl_display = gl::init::InitializeGLNoExtensionsOneOff(
  835. /*init_bindings=*/true, /*system_device_id=*/0);
  836. if (!gl_display) {
  837. VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
  838. << "with SwiftShader";
  839. return;
  840. }
  841. }
  842. }
  843. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  844. if (gl_use_swiftshader_) {
  845. AdjustInfoToSwiftShader();
  846. }
  847. #if defined(USE_OZONE)
  848. const std::vector<gfx::BufferFormat> supported_buffer_formats_for_texturing =
  849. ui::OzonePlatform::GetInstance()
  850. ->GetSurfaceFactoryOzone()
  851. ->GetSupportedFormatsForTexturing();
  852. gpu_feature_info_.supported_buffer_formats_for_allocation_and_texturing =
  853. std::move(supported_buffer_formats_for_texturing);
  854. #endif
  855. DisableInProcessGpuVulkan(&gpu_feature_info_, &gpu_preferences_);
  856. #if BUILDFLAG(IS_WIN)
  857. if (gpu_feature_info_.IsWorkaroundEnabled(DISABLE_DECODE_SWAP_CHAIN))
  858. gl::DisableDirectCompositionDecodeSwapChain();
  859. #endif
  860. UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
  861. }
  862. #endif // BUILDFLAG(IS_ANDROID)
  863. void GpuInit::SaveHardwareGpuInfoAndGpuFeatureInfo() {
  864. gpu_info_for_hardware_gpu_ = gpu_info_;
  865. gpu_feature_info_for_hardware_gpu_ = gpu_feature_info_;
  866. }
  867. void GpuInit::AdjustInfoToSwiftShader() {
  868. gpu_info_.passthrough_cmd_decoder = false;
  869. gpu_feature_info_ = ComputeGpuFeatureInfoForSwiftShader();
  870. CollectContextGraphicsInfo(&gpu_info_);
  871. DCHECK_EQ(gpu_info_.passthrough_cmd_decoder, false);
  872. }
  873. scoped_refptr<gl::GLSurface> GpuInit::TakeDefaultOffscreenSurface() {
  874. return std::move(default_offscreen_surface_);
  875. }
  876. bool GpuInit::InitializeVulkan() {
  877. #if BUILDFLAG(ENABLE_VULKAN)
  878. DCHECK_EQ(gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN],
  879. kGpuFeatureStatusEnabled);
  880. DCHECK_NE(gpu_preferences_.use_vulkan, VulkanImplementationName::kNone);
  881. bool vulkan_use_swiftshader =
  882. gpu_preferences_.use_vulkan == VulkanImplementationName::kSwiftshader;
  883. bool forced_native =
  884. gpu_preferences_.use_vulkan == VulkanImplementationName::kForcedNative;
  885. bool use_swiftshader = gl_use_swiftshader_ || vulkan_use_swiftshader;
  886. vulkan_implementation_ = CreateVulkanImplementation(
  887. vulkan_use_swiftshader, gpu_preferences_.enable_vulkan_protected_memory);
  888. if (!vulkan_implementation_ ||
  889. !vulkan_implementation_->InitializeVulkanInstance(
  890. !gpu_preferences_.disable_vulkan_surface)) {
  891. DLOG(ERROR) << "Failed to create and initialize Vulkan implementation.";
  892. vulkan_implementation_ = nullptr;
  893. CHECK(!gpu_preferences_.disable_vulkan_fallback_to_gl_for_testing);
  894. }
  895. // Vulkan info is no longer collected in gpu/config/gpu_info_collector_win.cc
  896. // Histogram GPU.SupportsVulkan and GPU.VulkanVersion were marked as expired.
  897. // TODO(magchen): Add back these two histograms here and re-enable them in
  898. // histograms.xml when we start Vulkan finch on Windows.
  899. if (!vulkan_implementation_)
  900. return false;
  901. const base::FeatureParam<std::string> disable_patterns(
  902. &features::kVulkan, "disable_by_gl_renderer",
  903. "*Mali-G?? M*" /* https://crbug.com/1183702 */);
  904. if (MatchGLInfo(gpu_info_.gl_renderer, disable_patterns.Get()))
  905. return false;
  906. const base::FeatureParam<std::string> disable_driver_patterns(
  907. &features::kVulkan, "disable_by_gl_driver",
  908. #if BUILDFLAG(IS_ANDROID)
  909. "324.0|331.0|334.0|378.0|415.0|420.0|444.0" /* https://crbug.com/1246857
  910. */
  911. #else
  912. ""
  913. #endif
  914. );
  915. if (MatchGLInfo(gpu_info_.gpu.driver_version, disable_driver_patterns.Get()))
  916. return false;
  917. const base::FeatureParam<std::string> force_enable_patterns(
  918. &features::kVulkan, "force_enable_by_gl_renderer", "");
  919. forced_native |=
  920. MatchGLInfo(gpu_info_.gl_renderer, force_enable_patterns.Get());
  921. const base::FeatureParam<std::string> enable_by_device_name(
  922. &features::kVulkan, "enable_by_device_name", "");
  923. if (!use_swiftshader && !forced_native &&
  924. !CheckVulkanCompabilities(
  925. vulkan_implementation_->GetVulkanInstance()->vulkan_info(), gpu_info_,
  926. enable_by_device_name.Get())) {
  927. vulkan_implementation_.reset();
  928. return false;
  929. }
  930. gpu_info_.vulkan_info =
  931. vulkan_implementation_->GetVulkanInstance()->vulkan_info();
  932. return true;
  933. #else // !BUILDFLAG(ENABLE_VULKAN)
  934. return false;
  935. #endif // BUILDFLAG(ENABLE_VULKAN)
  936. }
  937. } // namespace gpu