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 
5 #include "gpu/ipc/service/gpu_init.h"
6 
7 #include <string>
8 
9 #include "base/command_line.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/threading/scoped_blocking_call.h"
13 #include "base/trace_event/trace_event.h"
14 #include "build/build_config.h"
15 #include "build/chromecast_buildflags.h"
16 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
17 #include "gpu/command_buffer/service/gpu_switches.h"
18 #include "gpu/command_buffer/service/service_utils.h"
19 #include "gpu/config/gpu_driver_bug_list.h"
20 #include "gpu/config/gpu_driver_bug_workaround_type.h"
21 #include "gpu/config/gpu_finch_features.h"
22 #include "gpu/config/gpu_info_collector.h"
23 #include "gpu/config/gpu_switches.h"
24 #include "gpu/config/gpu_switching.h"
25 #include "gpu/config/gpu_util.h"
26 #include "gpu/ipc/service/gpu_watchdog_thread.h"
27 #include "gpu/ipc/service/gpu_watchdog_thread_v2.h"
28 #include "ui/base/ui_base_features.h"
29 #include "ui/gfx/switches.h"
30 #include "ui/gl/buildflags.h"
31 #include "ui/gl/gl_implementation.h"
32 #include "ui/gl/gl_surface.h"
33 #include "ui/gl/gl_switches.h"
34 #include "ui/gl/gl_utils.h"
35 #include "ui/gl/init/gl_factory.h"
36 
37 #if defined(OS_MACOSX)
38 #include <GLES2/gl2.h>
39 #endif
40 
41 #if defined(USE_OZONE)
42 #include "ui/ozone/public/ozone_platform.h"
43 #include "ui/ozone/public/surface_factory_ozone.h"
44 #endif
45 
46 #if defined(OS_WIN) && !defined(TOOLKIT_QT)
47 #include "ui/gl/gl_surface_egl.h"
48 #endif
49 
50 #if defined(OS_ANDROID)
51 #include "base/android/android_image_reader_compat.h"
52 #include "ui/gl/android/android_surface_control_compat.h"
53 #endif
54 
55 #if BUILDFLAG(ENABLE_VULKAN)
56 #include "gpu/vulkan/init/vulkan_factory.h"
57 #include "gpu/vulkan/vulkan_implementation.h"
58 #include "gpu/vulkan/vulkan_instance.h"
59 #endif
60 
61 namespace gpu {
62 
63 namespace {
CollectGraphicsInfo(GPUInfo * gpu_info)64 bool CollectGraphicsInfo(GPUInfo* gpu_info) {
65   DCHECK(gpu_info);
66   TRACE_EVENT0("gpu,startup", "Collect Graphics Info");
67   base::TimeTicks before_collect_context_graphics_info = base::TimeTicks::Now();
68   bool success = CollectContextGraphicsInfo(gpu_info);
69   if (!success)
70     LOG(ERROR) << "gpu::CollectGraphicsInfo failed.";
71 
72   if (success) {
73     base::TimeDelta collect_context_time =
74         base::TimeTicks::Now() - before_collect_context_graphics_info;
75     UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", collect_context_time);
76   }
77   return success;
78 }
79 
InitializePlatformOverlaySettings(GPUInfo * gpu_info)80 void InitializePlatformOverlaySettings(GPUInfo* gpu_info) {
81 #if defined(OS_WIN) && !defined(TOOLKIT_QT)
82   // This has to be called after a context is created, active GPU is identified,
83   // and GPU driver bug workarounds are computed again. Otherwise the workaround
84   // |disable_direct_composition| may not be correctly applied.
85   // Also, this has to be called after falling back to SwiftShader decision is
86   // finalized because this function depends on GL is ANGLE's GLES or not.
87   DCHECK(gpu_info);
88   CollectHardwareOverlayInfo(&gpu_info->overlay_info);
89 #elif defined(OS_ANDROID)
90   if (gpu_info->gpu.vendor_string == "Qualcomm")
91     gl::SurfaceControl::EnableQualcommUBWC();
92 #endif
93 }
94 
95 #if (defined(OS_LINUX) && !defined(OS_CHROMEOS) && !BUILDFLAG(IS_CHROMECAST)) || defined(OS_BSD)
CanAccessNvidiaDeviceFile()96 bool CanAccessNvidiaDeviceFile() {
97   bool res = true;
98   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
99                                                 base::BlockingType::WILL_BLOCK);
100   if (access("/dev/nvidiactl", R_OK) != 0) {
101     DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied";
102     res = false;
103   }
104   return res;
105 }
106 #endif  // (OS_LINUX && !OS_CHROMEOS && !BUILDFLAG(IS_CHROMECAST)) || defined(OS_BSD)
107 
108 class GpuWatchdogInit {
109  public:
110   GpuWatchdogInit() = default;
~GpuWatchdogInit()111   ~GpuWatchdogInit() {
112     if (watchdog_ptr_)
113       watchdog_ptr_->OnInitComplete();
114   }
115 
SetGpuWatchdogPtr(gpu::GpuWatchdogThread * ptr)116   void SetGpuWatchdogPtr(gpu::GpuWatchdogThread* ptr) { watchdog_ptr_ = ptr; }
117 
118  private:
119   gpu::GpuWatchdogThread* watchdog_ptr_ = nullptr;
120 };
121 }  // namespace
122 
123 GpuInit::GpuInit() = default;
124 
~GpuInit()125 GpuInit::~GpuInit() {
126   gpu::StopForceDiscreteGPU();
127 }
128 
InitializeAndStartSandbox(base::CommandLine * command_line,const GpuPreferences & gpu_preferences)129 bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line,
130                                         const GpuPreferences& gpu_preferences) {
131   gpu_preferences_ = gpu_preferences;
132 
133   if (gpu_preferences_.enable_perf_data_collection) {
134     // This is only enabled on the info collection GPU process.
135     DevicePerfInfo device_perf_info;
136     CollectDevicePerfInfo(&device_perf_info, /*in_browser_process=*/false);
137     device_perf_info_ = device_perf_info;
138   }
139 
140   // Blacklist decisions based on basic GPUInfo may not be final. It might
141   // need more context based GPUInfo. In such situations, switching to
142   // SwiftShader needs to wait until creating a context.
143   bool needs_more_info = true;
144 #if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMECAST)
145   needs_more_info = false;
146   if (!PopGPUInfoCache(&gpu_info_)) {
147     CollectBasicGraphicsInfo(command_line, &gpu_info_);
148   }
149 #if defined(OS_WIN)
150   IntelGpuSeriesType intel_gpu_series_type = GetIntelGpuSeriesType(
151       gpu_info_.active_gpu().vendor_id, gpu_info_.active_gpu().device_id);
152   UMA_HISTOGRAM_ENUMERATION("GPU.IntelGpuSeriesType", intel_gpu_series_type);
153 #endif  // OS_WIN
154 
155   // Set keys for crash logging based on preliminary gpu info, in case we
156   // crash during feature collection.
157   gpu::SetKeysForCrashLogging(gpu_info_);
158 #if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
159   gpu_info_.subpixel_font_rendering = false;
160 #else
161   gpu_info_.subpixel_font_rendering = true;
162 #endif
163 
164 #if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_BSD)
165   if (gpu_info_.gpu.vendor_id == 0x10de &&  // NVIDIA
166       gpu_info_.gpu.driver_vendor == "NVIDIA" && !CanAccessNvidiaDeviceFile())
167     return false;
168 #endif
169   if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) {
170     // Compute blacklist and driver bug workaround decisions based on basic GPU
171     // info.
172     gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
173         gpu_info_, gpu_preferences_, command_line, &needs_more_info);
174   }
175 #endif  // !OS_ANDROID && !BUILDFLAG(IS_CHROMECAST)
176 
177   gpu_info_.in_process_gpu = false;
178   bool use_swiftshader = false;
179 
180   // GL bindings may have already been initialized, specifically on MacOSX.
181   bool gl_initialized = gl::GetGLImplementation() != gl::kGLImplementationNone;
182   if (!gl_initialized) {
183     // If GL has already been initialized, then it's too late to select GPU.
184     if (gpu::SwitchableGPUsSupported(gpu_info_, *command_line)) {
185       gpu::InitializeSwitchableGPUs(
186           gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
187     }
188   } else if (gl::GetGLImplementation() == gl::kGLImplementationSwiftShaderGL &&
189              command_line->GetSwitchValueASCII(switches::kUseGL) !=
190                  gl::kGLImplementationSwiftShaderName) {
191     use_swiftshader = true;
192   }
193 
194   bool enable_watchdog = !gpu_preferences_.disable_gpu_watchdog &&
195                          !command_line->HasSwitch(switches::kHeadless) &&
196                          !use_swiftshader;
197 
198   // Disable the watchdog in debug builds because they tend to only be run by
199   // developers who will not appreciate the watchdog killing the GPU process.
200 #ifndef NDEBUG
201   enable_watchdog = false;
202 #endif
203 
204   // watchdog_init will call watchdog OnInitComplete() at the end of this
205   // function.
206   GpuWatchdogInit watchdog_init;
207 
208   bool delayed_watchdog_enable = false;
209 
210 #if defined(OS_CHROMEOS)
211   // Don't start watchdog immediately, to allow developers to switch to VT2 on
212   // startup.
213   delayed_watchdog_enable = true;
214 #endif
215 
216 #if defined(OS_LINUX) || defined(OS_BSD)
217   // PreSandbox is mainly for resource handling and not related to the GPU
218   // driver, it doesn't need the GPU watchdog. The loadLibrary may take long
219   // time that killing and restarting the GPU process will not help.
220   if (gpu_preferences_.gpu_sandbox_start_early) {
221     // The sandbox will be started earlier than usual (i.e. before GL) so
222     // execute the pre-sandbox steps now.
223     sandbox_helper_->PreSandboxStartup();
224   }
225 #else
226   // For some reasons MacOSX's VideoToolbox might crash when called after
227   // initializing GL, see crbug.com/1047643 and crbug.com/871280. On other
228   // operating systems like Windows and Android the pre-sandbox steps have
229   // always been executed before initializing GL so keep it this way.
230   sandbox_helper_->PreSandboxStartup();
231 #endif
232 
233   // Start the GPU watchdog only after anything that is expected to be time
234   // consuming has completed, otherwise the process is liable to be aborted.
235   if (enable_watchdog && !delayed_watchdog_enable) {
236     if (base::FeatureList::IsEnabled(features::kGpuWatchdogV2)) {
237       watchdog_thread_ = gpu::GpuWatchdogThreadImplV2::Create(
238           gpu_preferences_.watchdog_starts_backgrounded);
239       watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
240     } else {
241       watchdog_thread_ = gpu::GpuWatchdogThreadImplV1::Create(
242           gpu_preferences_.watchdog_starts_backgrounded);
243     }
244 
245 #if defined(OS_WIN)
246     // This is a workaround for an occasional deadlock between watchdog and
247     // current thread. Watchdog hangs at thread initialization in
248     // __acrt_thread_attach() and current thread in std::setlocale(...)
249     // (during InitializeGLOneOff()). Source of the deadlock looks like an old
250     // UCRT bug that was supposed to be fixed in 10.0.10586 release of UCRT,
251     // but we might have come accross a not-yet-covered scenario.
252     // References:
253     // https://bugs.python.org/issue26624
254     // http://stackoverflow.com/questions/35572792/setlocale-stuck-on-windows
255     auto watchdog_started = watchdog_thread_->WaitUntilThreadStarted();
256     DCHECK(watchdog_started);
257 #endif  // OS_WIN
258   }
259 
260   bool attempted_startsandbox = false;
261 #if defined(OS_LINUX) && !defined(OS_BSD)
262   // On Chrome OS ARM Mali, GPU driver userspace creates threads when
263   // initializing a GL context, so start the sandbox early.
264   // TODO(zmo): Need to collect OS version before this.
265   if (gpu_preferences_.gpu_sandbox_start_early) {
266     gpu_info_.sandboxed = sandbox_helper_->EnsureSandboxInitialized(
267         watchdog_thread_.get(), &gpu_info_, gpu_preferences_);
268     attempted_startsandbox = true;
269   }
270 #endif  // defined(OS_LINUX) && !defined(OS_BSD)
271 
272   base::TimeTicks before_initialize_one_off = base::TimeTicks::Now();
273 
274 #if defined(USE_OZONE)
275   // Initialize Ozone GPU after the watchdog in case it hangs. The sandbox
276   // may also have started at this point.
277   ui::OzonePlatform::InitParams params;
278   params.single_process = false;
279   params.using_mojo = features::IsOzoneDrmMojo();
280   ui::OzonePlatform::InitializeForGPU(params);
281   const std::vector<gfx::BufferFormat> supported_buffer_formats_for_texturing =
282       ui::OzonePlatform::GetInstance()
283           ->GetSurfaceFactoryOzone()
284           ->GetSupportedFormatsForTexturing();
285 #endif
286 
287   if (!use_swiftshader) {
288     use_swiftshader = EnableSwiftShaderIfNeeded(
289         command_line, gpu_feature_info_,
290         gpu_preferences_.disable_software_rasterizer, needs_more_info);
291   }
292   if (gl_initialized && use_swiftshader &&
293       gl::GetGLImplementation() != gl::kGLImplementationSwiftShaderGL) {
294 #if defined(OS_LINUX) || defined(OS_BSD)
295     VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
296             << "on Linux";
297     return false;
298 #else
299     gl::init::ShutdownGL(true);
300     gl_initialized = false;
301 #endif  // OS_LINUX || OS_BSD
302   }
303 
304   if (!gl_initialized) {
305     // Pause watchdog. LoadLibrary in GLBindings may take long time.
306     if (watchdog_thread_)
307       watchdog_thread_->PauseWatchdog();
308     gl_initialized = gl::init::InitializeStaticGLBindingsOneOff();
309 
310     if (!gl_initialized) {
311       VLOG(1) << "gl::init::InitializeStaticGLBindingsOneOff failed";
312       return false;
313     }
314 
315     if (watchdog_thread_)
316       watchdog_thread_->ResumeWatchdog();
317     if (gl::GetGLImplementation() != gl::kGLImplementationDisabled) {
318       gl_initialized =
319           gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ false);
320       if (!gl_initialized) {
321         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
322         return false;
323       }
324     }
325   }
326 
327 #if defined(OS_LINUX) && !defined(OS_BSD)
328   // The ContentSandboxHelper is currently the only one implementation of
329   // gpu::GpuSandboxHelper and it has no dependency. Except on Linux where
330   // VaapiWrapper checks the GL implementation to determine which display
331   // to use. So call PreSandboxStartup after GL initialization. But make
332   // sure the watchdog is paused as loadLibrary may take a long time and
333   // restarting the GPU process will not help.
334   if (!attempted_startsandbox) {
335     if (watchdog_thread_)
336       watchdog_thread_->PauseWatchdog();
337 
338     // The sandbox is not started yet.
339     sandbox_helper_->PreSandboxStartup();
340 
341     if (watchdog_thread_)
342       watchdog_thread_->ResumeWatchdog();
343   }
344 #endif
345 
346   // On MacOS, the default texture target for native GpuMemoryBuffers is
347   // GL_TEXTURE_RECTANGLE_ARB. This is due to CGL's requirements for creating
348   // a GL surface. However, when ANGLE is used on top of SwiftShader, it's
349   // necessary to use GL_TEXTURE_2D instead.
350   // TODO(crbug.com/1056312): The proper behavior is to check the config
351   // parameter set by the EGL_ANGLE_iosurface_client_buffer extension
352 #if defined(OS_MACOSX)
353   if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE &&
354       gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader) {
355     gpu::SetMacOSSpecificTextureTarget(GL_TEXTURE_2D);
356   }
357 #endif  // defined(OS_MACOSX)
358 
359   bool gl_disabled = gl::GetGLImplementation() == gl::kGLImplementationDisabled;
360 
361   // Compute passthrough decoder status before ComputeGpuFeatureInfo below.
362   gpu_info_.passthrough_cmd_decoder =
363       gles2::UsePassthroughCommandDecoder(command_line) &&
364       gles2::PassthroughCommandDecoderSupported();
365 
366   // We need to collect GL strings (VENDOR, RENDERER) for blacklisting purposes.
367   if (!gl_disabled) {
368     if (!use_swiftshader) {
369       if (!CollectGraphicsInfo(&gpu_info_))
370         return false;
371       gpu::SetKeysForCrashLogging(gpu_info_);
372       gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
373           gpu_info_, gpu_preferences_, command_line, nullptr);
374       use_swiftshader = EnableSwiftShaderIfNeeded(
375           command_line, gpu_feature_info_,
376           gpu_preferences_.disable_software_rasterizer, false);
377       if (use_swiftshader) {
378 #if defined(OS_LINUX) || defined(OS_BSD)
379         VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
380                 << "on Linux";
381         return false;
382 #else
383         gl::init::ShutdownGL(true);
384         watchdog_thread_ = nullptr;
385         watchdog_init.SetGpuWatchdogPtr(nullptr);
386         if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
387           VLOG(1)
388               << "gl::init::InitializeGLNoExtensionsOneOff with SwiftShader "
389               << "failed";
390           return false;
391         }
392 #endif  // OS_LINUX || OS_BSD
393       }
394     } else {  // use_swiftshader == true
395       switch (gpu_preferences_.use_vulkan) {
396         case gpu::VulkanImplementationName::kNative: {
397           // Collect GPU info, so we can use blacklist to disable vulkan if it
398           // is needed.
399           gpu::GPUInfo gpu_info;
400           if (!CollectGraphicsInfo(&gpu_info))
401             return false;
402           auto gpu_feature_info = gpu::ComputeGpuFeatureInfo(
403               gpu_info, gpu_preferences_, command_line, nullptr);
404           gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
405               gpu_feature_info.status_values[gpu::GPU_FEATURE_TYPE_VULKAN];
406           break;
407         }
408         case gpu::VulkanImplementationName::kForcedNative:
409         case gpu::VulkanImplementationName::kSwiftshader:
410           gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
411               gpu::kGpuFeatureStatusEnabled;
412           break;
413         case gpu::VulkanImplementationName::kNone:
414           gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
415               gpu::kGpuFeatureStatusDisabled;
416           break;
417       }
418     }
419   }
420 
421   InitializeVulkan();
422 
423   // Collect GPU process info
424   if (!gl_disabled) {
425     if (!CollectGpuExtraInfo(&gpu_extra_info_, gpu_preferences))
426       return false;
427   }
428 
429   if (!gl_disabled) {
430     if (!gpu_feature_info_.disabled_extensions.empty()) {
431       gl::init::SetDisabledExtensionsPlatform(
432           gpu_feature_info_.disabled_extensions);
433     }
434     if (!gl::init::InitializeExtensionSettingsOneOffPlatform()) {
435       VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
436       return false;
437     }
438     default_offscreen_surface_ =
439         gl::init::CreateOffscreenGLSurface(gfx::Size());
440     if (!default_offscreen_surface_) {
441       VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
442       return false;
443     }
444   }
445 
446   InitializePlatformOverlaySettings(&gpu_info_);
447 
448 #if defined(OS_LINUX) || defined(OS_BSD)
449   // Driver may create a compatibility profile context when collect graphics
450   // information on Linux platform. Try to collect graphics information
451   // based on core profile context after disabling platform extensions.
452   if (!gl_disabled && !use_swiftshader) {
453     if (!CollectGraphicsInfo(&gpu_info_))
454       return false;
455     gpu::SetKeysForCrashLogging(gpu_info_);
456     gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
457                                                    command_line, nullptr);
458     use_swiftshader = EnableSwiftShaderIfNeeded(
459         command_line, gpu_feature_info_,
460         gpu_preferences_.disable_software_rasterizer, false);
461     if (use_swiftshader) {
462       VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
463               << "on Linux";
464       return false;
465     }
466   }
467 #endif  // defined(OS_LINUX) || defined(OS_BSD)
468 
469   if (use_swiftshader) {
470     AdjustInfoToSwiftShader();
471   }
472 
473   if (kGpuFeatureStatusEnabled !=
474       gpu_feature_info_
475           .status_values[GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE]) {
476     gpu_preferences_.disable_accelerated_video_decode = true;
477   }
478 
479   base::TimeDelta initialize_one_off_time =
480       base::TimeTicks::Now() - before_initialize_one_off;
481   UMA_HISTOGRAM_MEDIUM_TIMES("GPU.InitializeOneOffMediumTime",
482                              initialize_one_off_time);
483 
484   // Software GL is expected to run slowly, so disable the watchdog
485   // in that case.
486   // In SwiftShader case, the implementation is actually EGLGLES2.
487   if (!use_swiftshader && command_line->HasSwitch(switches::kUseGL)) {
488     std::string use_gl = command_line->GetSwitchValueASCII(switches::kUseGL);
489     if (use_gl == gl::kGLImplementationSwiftShaderName ||
490         use_gl == gl::kGLImplementationSwiftShaderForWebGLName) {
491       use_swiftshader = true;
492     }
493   }
494   if (use_swiftshader ||
495       gl::GetGLImplementation() == gl::GetSoftwareGLImplementation()) {
496     gpu_info_.software_rendering = true;
497     watchdog_thread_ = nullptr;
498     watchdog_init.SetGpuWatchdogPtr(nullptr);
499   } else if (gl_disabled) {
500     watchdog_thread_ = nullptr;
501     watchdog_init.SetGpuWatchdogPtr(nullptr);
502   } else if (enable_watchdog && delayed_watchdog_enable) {
503     if (base::FeatureList::IsEnabled(features::kGpuWatchdogV2)) {
504       watchdog_thread_ = gpu::GpuWatchdogThreadImplV2::Create(
505           gpu_preferences_.watchdog_starts_backgrounded);
506       watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
507     } else {
508       watchdog_thread_ = gpu::GpuWatchdogThreadImplV1::Create(
509           gpu_preferences_.watchdog_starts_backgrounded);
510     }
511   }
512 
513   UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
514 
515   if (!gpu_info_.sandboxed && !attempted_startsandbox) {
516     gpu_info_.sandboxed = sandbox_helper_->EnsureSandboxInitialized(
517         watchdog_thread_.get(), &gpu_info_, gpu_preferences_);
518   }
519   UMA_HISTOGRAM_BOOLEAN("GPU.Sandbox.InitializedSuccessfully",
520                         gpu_info_.sandboxed);
521 
522   init_successful_ = true;
523 #if defined(USE_OZONE)
524   ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
525 #endif
526 
527 #if defined(USE_OZONE)
528   gpu_feature_info_.supported_buffer_formats_for_allocation_and_texturing =
529       std::move(supported_buffer_formats_for_texturing);
530 #endif
531 
532   if (!watchdog_thread_)
533     watchdog_init.SetGpuWatchdogPtr(nullptr);
534 
535   return true;
536 }
537 
538 #if defined(OS_ANDROID)
InitializeInProcess(base::CommandLine * command_line,const GpuPreferences & gpu_preferences)539 void GpuInit::InitializeInProcess(base::CommandLine* command_line,
540                                   const GpuPreferences& gpu_preferences) {
541   gpu_preferences_ = gpu_preferences;
542   init_successful_ = true;
543   DCHECK(!EnableSwiftShaderIfNeeded(
544       command_line, gpu_feature_info_,
545       gpu_preferences_.disable_software_rasterizer, false));
546 
547   InitializeGLThreadSafe(command_line, gpu_preferences_, &gpu_info_,
548                          &gpu_feature_info_);
549   InitializeVulkan();
550 
551   default_offscreen_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
552 
553   UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
554 }
555 #else
InitializeInProcess(base::CommandLine * command_line,const GpuPreferences & gpu_preferences)556 void GpuInit::InitializeInProcess(base::CommandLine* command_line,
557                                   const GpuPreferences& gpu_preferences) {
558   gpu_preferences_ = gpu_preferences;
559   init_successful_ = true;
560 #if defined(USE_OZONE)
561   ui::OzonePlatform::InitParams params;
562   params.single_process = true;
563   params.using_mojo = features::IsOzoneDrmMojo();
564   ui::OzonePlatform::InitializeForGPU(params);
565   const std::vector<gfx::BufferFormat> supported_buffer_formats_for_texturing =
566       ui::OzonePlatform::GetInstance()
567           ->GetSurfaceFactoryOzone()
568           ->GetSupportedFormatsForTexturing();
569 #endif
570   bool needs_more_info = true;
571 #if !BUILDFLAG(IS_CHROMECAST)
572   needs_more_info = false;
573   if (!PopGPUInfoCache(&gpu_info_)) {
574     CollectBasicGraphicsInfo(command_line, &gpu_info_);
575   }
576 #if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
577   gpu_info_.subpixel_font_rendering = false;
578 #else
579   gpu_info_.subpixel_font_rendering = true;
580 #endif
581   if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) {
582     gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
583                                               command_line, &needs_more_info);
584   }
585   if (SwitchableGPUsSupported(gpu_info_, *command_line)) {
586     InitializeSwitchableGPUs(
587         gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
588   }
589 #endif  // !BUILDFLAG(IS_CHROMECAST)
590 
591   bool use_swiftshader = EnableSwiftShaderIfNeeded(
592       command_line, gpu_feature_info_,
593       gpu_preferences_.disable_software_rasterizer, needs_more_info);
594   if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
595     VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed";
596     return;
597   }
598   bool gl_disabled = gl::GetGLImplementation() == gl::kGLImplementationDisabled;
599 
600   if (!gl_disabled && !use_swiftshader) {
601     CollectContextGraphicsInfo(&gpu_info_);
602     gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
603                                               command_line, nullptr);
604     use_swiftshader = EnableSwiftShaderIfNeeded(
605         command_line, gpu_feature_info_,
606         gpu_preferences_.disable_software_rasterizer, false);
607     if (use_swiftshader) {
608       gl::init::ShutdownGL(true);
609       if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
610         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
611                 << "with SwiftShader";
612         return;
613       }
614     }
615   }
616 
617   if (!gl_disabled) {
618     if (!gpu_feature_info_.disabled_extensions.empty()) {
619       gl::init::SetDisabledExtensionsPlatform(
620           gpu_feature_info_.disabled_extensions);
621     }
622     if (!gl::init::InitializeExtensionSettingsOneOffPlatform()) {
623       VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
624     }
625     default_offscreen_surface_ =
626         gl::init::CreateOffscreenGLSurface(gfx::Size());
627     if (!default_offscreen_surface_) {
628       VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
629     }
630   }
631 
632   InitializePlatformOverlaySettings(&gpu_info_);
633 
634 #if defined(OS_LINUX) || defined(OS_BSD)
635   // Driver may create a compatibility profile context when collect graphics
636   // information on Linux platform. Try to collect graphics information
637   // based on core profile context after disabling platform extensions.
638   if (!gl_disabled && !use_swiftshader) {
639     CollectContextGraphicsInfo(&gpu_info_);
640     gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
641                                               command_line, nullptr);
642     use_swiftshader = EnableSwiftShaderIfNeeded(
643         command_line, gpu_feature_info_,
644         gpu_preferences_.disable_software_rasterizer, false);
645     if (use_swiftshader) {
646       gl::init::ShutdownGL(true);
647       if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
648         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
649                 << "with SwiftShader";
650         return;
651       }
652     }
653   }
654 #endif  // defined(OS_LINUX) || defined(OS_BSD)
655 
656   if (use_swiftshader) {
657     AdjustInfoToSwiftShader();
658   }
659 
660 #if defined(USE_OZONE)
661   gpu_feature_info_.supported_buffer_formats_for_allocation_and_texturing =
662       std::move(supported_buffer_formats_for_texturing);
663 #endif
664 
665   UMA_HISTOGRAM_ENUMERATION("GPU.GLImplementation", gl::GetGLImplementation());
666 }
667 #endif  // OS_ANDROID
668 
AdjustInfoToSwiftShader()669 void GpuInit::AdjustInfoToSwiftShader() {
670   gpu_info_for_hardware_gpu_ = gpu_info_;
671   gpu_info_.passthrough_cmd_decoder = false;
672   gpu_feature_info_for_hardware_gpu_ = gpu_feature_info_;
673   gpu_feature_info_ = ComputeGpuFeatureInfoForSwiftShader();
674   CollectContextGraphicsInfo(&gpu_info_);
675 }
676 
TakeDefaultOffscreenSurface()677 scoped_refptr<gl::GLSurface> GpuInit::TakeDefaultOffscreenSurface() {
678   return std::move(default_offscreen_surface_);
679 }
680 
InitializeVulkan()681 void GpuInit::InitializeVulkan() {
682 #if BUILDFLAG(ENABLE_VULKAN)
683   if (gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] ==
684       gpu::kGpuFeatureStatusEnabled) {
685     DCHECK_NE(gpu_preferences_.use_vulkan,
686               gpu::VulkanImplementationName::kNone);
687     bool vulkan_use_swiftshader = gpu_preferences_.use_vulkan ==
688                                   gpu::VulkanImplementationName::kSwiftshader;
689     const bool enforce_protected_memory =
690         gpu_preferences_.enforce_vulkan_protected_memory;
691     vulkan_implementation_ = gpu::CreateVulkanImplementation(
692         vulkan_use_swiftshader,
693         enforce_protected_memory ? true : false /* allow_protected_memory */,
694         enforce_protected_memory);
695     if (!vulkan_implementation_ ||
696         !vulkan_implementation_->InitializeVulkanInstance(
697             !gpu_preferences_.disable_vulkan_surface)) {
698       DLOG(ERROR) << "Failed to create and initialize Vulkan implementation.";
699       vulkan_implementation_ = nullptr;
700       CHECK(!gpu_preferences_.disable_vulkan_fallback_to_gl_for_testing);
701     }
702     // TODO(penghuang): Remove GPU.SupportsVulkan and GPU.VulkanVersion from
703     // //gpu/config/gpu_info_collector_win.cc when we are finch vulkan on
704     // Windows.
705     if (!vulkan_use_swiftshader) {
706       const bool supports_vulkan = !!vulkan_implementation_;
707       UMA_HISTOGRAM_BOOLEAN("GPU.SupportsVulkan", supports_vulkan);
708       uint32_t vulkan_version = 0;
709       if (supports_vulkan) {
710         const auto& vulkan_info =
711             vulkan_implementation_->GetVulkanInstance()->vulkan_info();
712         vulkan_version = vulkan_info.used_api_version;
713       }
714       UMA_HISTOGRAM_ENUMERATION(
715           "GPU.VulkanVersion", ConvertToHistogramVulkanVersion(vulkan_version));
716     }
717   }
718   if (!vulkan_implementation_) {
719     if (gpu_preferences_.gr_context_type == gpu::GrContextType::kVulkan) {
720       gpu_preferences_.gr_context_type = gpu::GrContextType::kGL;
721     }
722     gpu_preferences_.use_vulkan = gpu::VulkanImplementationName::kNone;
723     gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
724         gpu::kGpuFeatureStatusDisabled;
725   } else {
726     gpu_info_.vulkan_info =
727         vulkan_implementation_->GetVulkanInstance()->vulkan_info();
728   }
729 #else
730   gpu_preferences_.use_vulkan = gpu::VulkanImplementationName::kNone;
731   gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
732       gpu::kGpuFeatureStatusDisabled;
733 #endif  // BUILDFLAG(ENABLE_VULKAN)
734 }
735 
736 }  // namespace gpu
737