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