diff options
Diffstat (limited to 'chromium/content/browser/gpu')
17 files changed, 773 insertions, 422 deletions
diff --git a/chromium/content/browser/gpu/OWNERS b/chromium/content/browser/gpu/OWNERS index c45f8fa6e23..55d9b9bde3d 100644 --- a/chromium/content/browser/gpu/OWNERS +++ b/chromium/content/browser/gpu/OWNERS @@ -1,5 +1,6 @@ kbr@chromium.org piman@chromium.org zmo@chromium.org +backer@chromium.org # COMPONENT: Internals>GPU>Internals diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc index cdc4d3d678a..ca32413b3f3 100644 --- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -4,6 +4,7 @@ #include "content/browser/gpu/browser_gpu_channel_host_factory.h" +#include "base/android/orderfile/orderfile_buildflags.h" #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" @@ -15,6 +16,7 @@ #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "components/viz/common/features.h" #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/gpu/gpu_process_host.h" @@ -26,10 +28,15 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/ipc/in_process_command_buffer.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h" #include "services/service_manager/runner/common/client_util.h" #include "ui/base/ui_base_features.h" +#if defined(OS_MACOSX) +#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" +#endif + namespace content { #if defined(OS_ANDROID) @@ -105,7 +112,13 @@ BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest( gpu_client_id_(gpu_client_id), gpu_client_tracing_id_(gpu_client_tracing_id), finished_(false), - main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} +#if defined(OS_MACOSX) + main_task_runner_(ui::WindowResizeHelperMac::Get()->task_runner()) +#else + main_task_runner_(base::ThreadTaskRunnerHandle::Get()) +#endif +{ +} void BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout() { BrowserGpuChannelHostFactory* factory = @@ -273,7 +286,7 @@ BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() { void BrowserGpuChannelHostFactory::EstablishGpuChannel( gpu::GpuChannelEstablishedCallback callback) { #if defined(USE_AURA) - DCHECK(!base::FeatureList::IsEnabled(::features::kMash)); + DCHECK(features::IsAshInBrowserProcess()); #endif DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (gpu_channel_.get() && gpu_channel_->IsLost()) { @@ -352,7 +365,7 @@ void BrowserGpuChannelHostFactory::RestartTimeout() { return; #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \ - defined(CYGPROFILE_INSTRUMENTATION) + BUILDFLAG(ORDERFILE_INSTRUMENTATION) constexpr int64_t kGpuChannelTimeoutInSeconds = 40; #else // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to @@ -371,6 +384,10 @@ void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO( int gpu_client_id, const base::FilePath& cache_dir) { GetShaderCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir); + if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) { + GetShaderCacheFactorySingleton()->SetCacheInfo( + gpu::InProcessCommandBuffer::kGpuClientId, cache_dir); + } } } // namespace content diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc index 22d03d380b4..8568d3f5885 100644 --- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc +++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc @@ -141,7 +141,7 @@ void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess( auto handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( id, size, format, usage); buffers.find(id)->second.shared_memory_guid = handle.handle.GetGUID(); - std::move(callback).Run(handle); + std::move(callback).Run(std::move(handle)); } void BrowserGpuMemoryBufferManager::SetDestructionSyncToken( @@ -310,7 +310,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO( void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO( CreateGpuMemoryBufferRequest* request, - const gfx::GpuMemoryBufferHandle& handle) { + gfx::GpuMemoryBufferHandle handle) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // Early out if factory failed to create the buffer. @@ -321,15 +321,16 @@ void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO( // Note: Unretained is safe as IO thread is stopped before manager is // destroyed. + auto handle_id = handle.id; request->result = gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle( - handle, request->size, request->format, request->usage, + std::move(handle), request->size, request->format, request->usage, base::Bind( &GpuMemoryBufferDeleted, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), base::Bind( &BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, - base::Unretained(this), handle.id, request->client_id))); + base::Unretained(this), handle_id, request->client_id))); request->event.Signal(); } @@ -377,7 +378,7 @@ void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO( int client_id, int gpu_host_id, CreateCallback callback, - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, GpuProcessHost::BufferCreationStatus status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -432,7 +433,7 @@ void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO( buffer_it->second.gpu_host_id = gpu_host_id; buffer_it->second.shared_memory_guid = handle.handle.GetGUID(); - std::move(callback).Run(handle); + std::move(callback).Run(std::move(handle)); } void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO( diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h index 41843a9309c..4cf2b632fb0 100644 --- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h +++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h @@ -33,7 +33,7 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager public base::trace_event::MemoryDumpProvider { public: using CreateCallback = - base::OnceCallback<void(const gfx::GpuMemoryBufferHandle& handle)>; + base::OnceCallback<void(gfx::GpuMemoryBufferHandle handle)>; using AllocationCallback = CreateCallback; BrowserGpuMemoryBufferManager(int gpu_client_id, @@ -98,9 +98,8 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager // Functions that handle synchronous buffer creation requests. void HandleCreateGpuMemoryBufferOnIO(CreateGpuMemoryBufferRequest* request); - void HandleGpuMemoryBufferCreatedOnIO( - CreateGpuMemoryBufferRequest* request, - const gfx::GpuMemoryBufferHandle& handle); + void HandleGpuMemoryBufferCreatedOnIO(CreateGpuMemoryBufferRequest* request, + gfx::GpuMemoryBufferHandle handle); // Functions that implement asynchronous buffer creation. void CreateGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id, @@ -115,7 +114,7 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager int client_id, int gpu_host_id, CreateCallback callback, - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, GpuProcessHost::BufferCreationStatus status); void DestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id, int client_id, diff --git a/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc new file mode 100644 index 00000000000..8f3efa6a705 --- /dev/null +++ b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc @@ -0,0 +1,115 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/gpu/ca_transaction_gpu_coordinator.h" + +#include "base/cancelable_callback.h" +#include "content/browser/gpu/gpu_process_host.h" +#include "content/public/browser/browser_thread.h" +#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h" +#include "ui/accelerated_widget_mac/ca_transaction_observer.h" +#include "ui/accelerated_widget_mac/window_resize_helper_mac.h" + +namespace content { + +// static +scoped_refptr<CATransactionGPUCoordinator> CATransactionGPUCoordinator::Create( + GpuProcessHost* host) { + scoped_refptr<CATransactionGPUCoordinator> result( + new CATransactionGPUCoordinator(host)); + // Avoid modifying result's refcount in the constructor by performing this + // PostTask afterward. + DCHECK_CURRENTLY_ON(BrowserThread::IO); + ui::WindowResizeHelperMac::Get()->task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &CATransactionGPUCoordinator::AddPostCommitObserverOnUIThread, + result)); + return result; +} + +CATransactionGPUCoordinator::CATransactionGPUCoordinator(GpuProcessHost* host) + : host_(host) {} + +CATransactionGPUCoordinator::~CATransactionGPUCoordinator() { + DCHECK(!host_); + DCHECK(!registered_as_observer_); +} + +void CATransactionGPUCoordinator::HostWillBeDestroyed() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + ui::WindowResizeHelperMac::Get()->task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &CATransactionGPUCoordinator::RemovePostCommitObserverOnUIThread, + this)); + host_ = nullptr; +} + +void CATransactionGPUCoordinator::AddPostCommitObserverOnUIThread() { + DCHECK(!registered_as_observer_); + ui::CATransactionCoordinator::Get().AddPostCommitObserver(this); + registered_as_observer_ = true; +} + +void CATransactionGPUCoordinator::RemovePostCommitObserverOnUIThread() { + DCHECK(registered_as_observer_); + ui::CATransactionCoordinator::Get().RemovePostCommitObserver(this); + registered_as_observer_ = false; +} + +void CATransactionGPUCoordinator::OnActivateForTransaction() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::BindOnce(&CATransactionGPUCoordinator::OnActivateForTransactionOnIO, + this)); +} + +void CATransactionGPUCoordinator::OnEnterPostCommit() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // If HostWillBeDestroyed() is called during a commit, pending_commit_count_ + // may be left non-zero. That's fine as long as this instance is destroyed + // (and removed from the list of post-commit observers) soon after. + pending_commit_count_++; + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::BindOnce(&CATransactionGPUCoordinator::OnEnterPostCommitOnIO, + this)); +} + +bool CATransactionGPUCoordinator::ShouldWaitInPostCommit() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return pending_commit_count_ > 0; +} + +void CATransactionGPUCoordinator::OnActivateForTransactionOnIO() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (host_) + host_->gpu_service()->BeginCATransaction(); +} + +void CATransactionGPUCoordinator::OnEnterPostCommitOnIO() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (host_) + host_->gpu_service()->CommitCATransaction(base::BindOnce( + &CATransactionGPUCoordinator::OnCommitCompletedOnIO, this)); +} + +void CATransactionGPUCoordinator::OnCommitCompletedOnIO() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + ui::WindowResizeHelperMac::Get()->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&CATransactionGPUCoordinator::OnCommitCompletedOnUI, + this)); +} + +void CATransactionGPUCoordinator::OnCommitCompletedOnUI() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + pending_commit_count_--; +} + +} // namespace content diff --git a/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h new file mode 100644 index 00000000000..53b52a25d3f --- /dev/null +++ b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h @@ -0,0 +1,60 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_ +#define CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "ui/accelerated_widget_mac/ca_transaction_observer.h" + +#include <memory> + +namespace content { + +class GpuProcessHost; + +// Synchronizes CATransaction commits between the browser and GPU processes. +class CATransactionGPUCoordinator + : public ui::CATransactionCoordinator::PostCommitObserver { + public: + static scoped_refptr<CATransactionGPUCoordinator> Create( + GpuProcessHost* host); + void HostWillBeDestroyed(); + + private: + friend class base::RefCountedThreadSafe<CATransactionGPUCoordinator>; + CATransactionGPUCoordinator(GpuProcessHost* host); + ~CATransactionGPUCoordinator() override; + + // ui::CATransactionObserver implementation + void OnActivateForTransaction() override; + void OnEnterPostCommit() override; + bool ShouldWaitInPostCommit() override; + + void AddPostCommitObserverOnUIThread(); + void RemovePostCommitObserverOnUIThread(); + + void OnActivateForTransactionOnIO(); + void OnEnterPostCommitOnIO(); + void OnCommitCompletedOnIO(); + void OnCommitCompletedOnUI(); + + // The GpuProcessHost to use to initiate GPU-side CATransactions. This is only + // to be accessed on the IO thread. + GpuProcessHost* host_ = nullptr; + + // The number CATransactions that have not yet completed. This is only to be + // accessed on the UI thread. + int pending_commit_count_ = 0; + + // Egregious state tracking to debug https://crbug.com/871430 + bool registered_as_observer_ = false; + + DISALLOW_COPY_AND_ASSIGN(CATransactionGPUCoordinator); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_ diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc index db3b6606770..9773ec885ea 100644 --- a/chromium/content/browser/gpu/compositor_util.cc +++ b/chromium/content/browser/gpu/compositor_util.cc @@ -161,6 +161,13 @@ const GpuFeatureData GetGpuFeatureData( "Accelerated rasterization has been disabled, either via blacklist, " "about:flags or the command line.", true, true}, + {"oop_rasterization", + SafeGetFeatureStatus(gpu_feature_info, + gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION), + command_line.HasSwitch(switches::kDisableOopRasterization), + "Out-of-process accelerated rasterization has been disabled, either " + "via blacklist, about:flags or the command line.", + false, true}, {"multiple_raster_threads", gpu::kGpuFeatureStatusEnabled, NumberOfRendererRasterThreads() == 1, "Raster is using a single thread.", false, true}, @@ -215,8 +222,12 @@ std::unique_ptr<base::DictionaryValue> GetFeatureStatusImpl( const GpuFeatureData gpu_feature_data = GetGpuFeatureData(gpu_feature_info, type, i, &eof); std::string status; - if (gpu_feature_data.disabled || gpu_access_blocked || - gpu_feature_data.status == gpu::kGpuFeatureStatusDisabled) { + if (gpu_feature_data.name == "surface_synchronization") { + status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off"); + } else if (gpu_feature_data.name == "viz_display_compositor") { + status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off"); + } else if (gpu_feature_data.disabled || gpu_access_blocked || + gpu_feature_data.status == gpu::kGpuFeatureStatusDisabled) { status = "disabled"; if (gpu_feature_data.fallback_to_software) status += "_software"; @@ -244,14 +255,6 @@ std::unique_ptr<base::DictionaryValue> GetFeatureStatusImpl( status += "_force"; status += "_on"; } - if (gpu_feature_data.name == "surface_synchronization") { - if (features::IsSurfaceSynchronizationEnabled()) - status += "_on"; - } - if (gpu_feature_data.name == "viz_display_compositor") { - if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) - status += "_on"; - } if (gpu_feature_data.name == "skia_renderer") { if (features::IsUsingSkiaRenderer()) status += "_on"; diff --git a/chromium/content/browser/gpu/gpu_client_impl.cc b/chromium/content/browser/gpu/gpu_client_impl.cc index a591794d329..c2ef9591cd3 100644 --- a/chromium/content/browser/gpu/gpu_client_impl.cc +++ b/chromium/content/browser/gpu/gpu_client_impl.cc @@ -7,7 +7,6 @@ #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/common/child_process_host_impl.h" -#include "content/public/browser/browser_thread.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/common/gpu_memory_buffer_impl.h" #include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h" @@ -15,51 +14,67 @@ namespace content { // static -std::unique_ptr<GpuClient, BrowserThread::DeleteOnIOThread> GpuClient::Create( +std::unique_ptr<GpuClient, base::OnTaskRunnerDeleter> GpuClient::Create( ui::mojom::GpuRequest request, - ConnectionErrorHandlerClosure connection_error_handler) { - std::unique_ptr<GpuClientImpl, BrowserThread::DeleteOnIOThread> gpu_client( - new GpuClientImpl(ChildProcessHostImpl::GenerateChildProcessUniqueId())); + ConnectionErrorHandlerClosure connection_error_handler, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + const int client_id = ChildProcessHostImpl::GenerateChildProcessUniqueId(); + const uint64_t client_tracing_id = + ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(client_id); + std::unique_ptr<GpuClientImpl, base::OnTaskRunnerDeleter> gpu_client( + new GpuClientImpl(client_id, client_tracing_id, task_runner), + base::OnTaskRunnerDeleter(task_runner)); gpu_client->SetConnectionErrorHandler(std::move(connection_error_handler)); gpu_client->Add(std::move(request)); return gpu_client; } -GpuClientImpl::GpuClientImpl(int render_process_id) - : render_process_id_(render_process_id), weak_factory_(this) { - bindings_.set_connection_error_handler( - base::Bind(&GpuClientImpl::OnError, base::Unretained(this), - ErrorReason::kConnectionLost)); +GpuClientImpl::GpuClientImpl( + int client_id, + uint64_t client_tracing_id, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : client_id_(client_id), + client_tracing_id_(client_tracing_id), + task_runner_(std::move(task_runner)), + weak_factory_(this) { + gpu_bindings_.set_connection_error_handler( + base::BindRepeating(&GpuClientImpl::OnError, base::Unretained(this), + ErrorReason::kConnectionLost)); } GpuClientImpl::~GpuClientImpl() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - bindings_.CloseAllBindings(); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + gpu_bindings_.CloseAllBindings(); OnError(ErrorReason::kInDestructor); } void GpuClientImpl::Add(ui::mojom::GpuRequest request) { - bindings_.AddBinding(this, std::move(request)); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + gpu_bindings_.AddBinding(this, std::move(request)); } void GpuClientImpl::OnError(ErrorReason reason) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); ClearCallback(); - if (bindings_.empty()) { + if (gpu_bindings_.empty()) { BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager = BrowserGpuMemoryBufferManager::current(); if (gpu_memory_buffer_manager) - gpu_memory_buffer_manager->ProcessRemoved(render_process_id_); + gpu_memory_buffer_manager->ProcessRemoved(client_id_); } if (reason == ErrorReason::kConnectionLost && connection_error_handler_) std::move(connection_error_handler_).Run(this); } void GpuClientImpl::PreEstablishGpuChannel() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&GpuClientImpl::EstablishGpuChannel, - base::Unretained(this), EstablishGpuChannelCallback())); + if (task_runner_->RunsTasksInCurrentSequence()) { + EstablishGpuChannel(EstablishGpuChannelCallback()); + } else { + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&GpuClientImpl::EstablishGpuChannel, + base::Unretained(this), EstablishGpuChannelCallback())); + } } void GpuClientImpl::SetConnectionErrorHandler( @@ -85,8 +100,8 @@ void GpuClientImpl::OnEstablishGpuChannel( } if (callback) { // A request is waiting. - std::move(callback).Run(render_process_id_, std::move(channel_handle), - gpu_info, gpu_feature_info); + std::move(callback).Run(client_id_, std::move(channel_handle), gpu_info, + gpu_feature_info); return; } if (status == GpuProcessHost::EstablishChannelStatus::SUCCESS) { @@ -100,21 +115,21 @@ void GpuClientImpl::OnEstablishGpuChannel( void GpuClientImpl::OnCreateGpuMemoryBuffer( CreateGpuMemoryBufferCallback callback, - const gfx::GpuMemoryBufferHandle& handle) { - std::move(callback).Run(handle); + gfx::GpuMemoryBufferHandle handle) { + std::move(callback).Run(std::move(handle)); } void GpuClientImpl::ClearCallback() { if (!callback_) return; EstablishGpuChannelCallback callback = std::move(callback_); - std::move(callback).Run(render_process_id_, mojo::ScopedMessagePipeHandle(), + std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(), gpu::GpuFeatureInfo()); DCHECK(!callback_); } void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); // At most one channel should be requested. So clear previous request first. ClearCallback(); if (channel_handle_.is_valid()) { @@ -123,8 +138,8 @@ void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) { // 2) if callback is empty, it's PreEstablishGpyChannel() being called // more than once, no need to do anything. if (callback) { - std::move(callback).Run(render_process_id_, std::move(channel_handle_), - gpu_info_, gpu_feature_info_); + std::move(callback).Run(client_id_, std::move(channel_handle_), gpu_info_, + gpu_feature_info_); DCHECK(!channel_handle_.is_valid()); } return; @@ -132,9 +147,8 @@ void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) { GpuProcessHost* host = GpuProcessHost::Get(); if (!host) { if (callback) { - std::move(callback).Run(render_process_id_, - mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(), - gpu::GpuFeatureInfo()); + std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(), + gpu::GPUInfo(), gpu::GpuFeatureInfo()); } return; } @@ -146,12 +160,10 @@ void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) { bool allow_view_command_buffers = false; bool allow_real_time_streams = false; host->EstablishGpuChannel( - render_process_id_, - ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( - render_process_id_), - preempts, allow_view_command_buffers, allow_real_time_streams, - base::Bind(&GpuClientImpl::OnEstablishGpuChannel, - weak_factory_.GetWeakPtr())); + client_id_, client_tracing_id_, preempts, allow_view_command_buffers, + allow_real_time_streams, + base::BindRepeating(&GpuClientImpl::OnEstablishGpuChannel, + weak_factory_.GetWeakPtr())); } void GpuClientImpl::CreateJpegDecodeAccelerator( @@ -175,7 +187,7 @@ void GpuClientImpl::CreateGpuMemoryBuffer( const gfx::Size& size, gfx::BufferFormat format, gfx::BufferUsage usage, - ui::mojom::Gpu::CreateGpuMemoryBufferCallback callback) { + ui::mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback) { DCHECK(BrowserGpuMemoryBufferManager::current()); base::CheckedNumeric<int> bytes = size.width(); @@ -187,7 +199,7 @@ void GpuClientImpl::CreateGpuMemoryBuffer( BrowserGpuMemoryBufferManager::current() ->AllocateGpuMemoryBufferForChildProcess( - id, size, format, usage, render_process_id_, + id, size, format, usage, client_id_, base::BindOnce(&GpuClientImpl::OnCreateGpuMemoryBuffer, weak_factory_.GetWeakPtr(), std::move(callback))); } @@ -197,7 +209,12 @@ void GpuClientImpl::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, DCHECK(BrowserGpuMemoryBufferManager::current()); BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer( - id, render_process_id_, sync_token); + id, client_id_, sync_token); +} + +void GpuClientImpl::CreateGpuMemoryBufferFactory( + ui::mojom::GpuMemoryBufferFactoryRequest request) { + gpu_memory_buffer_factory_bindings_.AddBinding(this, std::move(request)); } } // namespace content diff --git a/chromium/content/browser/gpu/gpu_client_impl.h b/chromium/content/browser/gpu/gpu_client_impl.h index 03e29bf4b5f..70e684a68be 100644 --- a/chromium/content/browser/gpu/gpu_client_impl.h +++ b/chromium/content/browser/gpu/gpu_client_impl.h @@ -13,11 +13,19 @@ namespace content { -class GpuClientImpl : public ui::mojom::Gpu, public GpuClient { +class GpuClientImpl : public ui::mojom::GpuMemoryBufferFactory, + public ui::mojom::Gpu, + public GpuClient { public: - explicit GpuClientImpl(int render_process_id); + // GpuClientImpl must be destroyed on the thread associated with + // |task_runner|. + GpuClientImpl(int client_id, + uint64_t client_tracing_id, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); + ~GpuClientImpl() override; + // This needs to be run on the thread associated with |task_runner_|. void Add(ui::mojom::GpuRequest request); void PreEstablishGpuChannel(); @@ -25,6 +33,27 @@ class GpuClientImpl : public ui::mojom::Gpu, public GpuClient { void SetConnectionErrorHandler( ConnectionErrorHandlerClosure connection_error_handler); + // ui::mojom::GpuMemoryBufferFactory overrides: + void CreateGpuMemoryBuffer( + gfx::GpuMemoryBufferId id, + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferUsage usage, + ui::mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback) + override; + void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, + const gpu::SyncToken& sync_token) override; + + // ui::mojom::Gpu overrides: + void CreateGpuMemoryBufferFactory( + ui::mojom::GpuMemoryBufferFactoryRequest request) override; + void EstablishGpuChannel(EstablishGpuChannelCallback callback) override; + void CreateJpegDecodeAccelerator( + media::mojom::JpegDecodeAcceleratorRequest jda_request) override; + void CreateVideoEncodeAcceleratorProvider( + media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request) + override; + private: enum class ErrorReason { // OnError() is being called from the destructor. @@ -38,33 +67,24 @@ class GpuClientImpl : public ui::mojom::Gpu, public GpuClient { const gpu::GpuFeatureInfo& gpu_feature_info, GpuProcessHost::EstablishChannelStatus status); void OnCreateGpuMemoryBuffer(CreateGpuMemoryBufferCallback callback, - const gfx::GpuMemoryBufferHandle& handle); + gfx::GpuMemoryBufferHandle handle); void ClearCallback(); - // ui::mojom::Gpu overrides: - void EstablishGpuChannel(EstablishGpuChannelCallback callback) override; - void CreateJpegDecodeAccelerator( - media::mojom::JpegDecodeAcceleratorRequest jda_request) override; - void CreateVideoEncodeAcceleratorProvider( - media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request) - override; - void CreateGpuMemoryBuffer( - gfx::GpuMemoryBufferId id, - const gfx::Size& size, - gfx::BufferFormat format, - gfx::BufferUsage usage, - ui::mojom::Gpu::CreateGpuMemoryBufferCallback callback) override; - void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, - const gpu::SyncToken& sync_token) override; - - const int render_process_id_; - mojo::BindingSet<ui::mojom::Gpu> bindings_; + const int client_id_; + const uint64_t client_tracing_id_; + mojo::BindingSet<ui::mojom::GpuMemoryBufferFactory> + gpu_memory_buffer_factory_bindings_; + mojo::BindingSet<ui::mojom::Gpu> gpu_bindings_; bool gpu_channel_requested_ = false; EstablishGpuChannelCallback callback_; mojo::ScopedMessagePipeHandle channel_handle_; gpu::GPUInfo gpu_info_; gpu::GpuFeatureInfo gpu_feature_info_; ConnectionErrorHandlerClosure connection_error_handler_; + // |task_runner_| is associated with the thread |gpu_bindings_| is bound on. + // GpuClientImpl instance is bound to this thread, and must be destroyed on + // this thread. + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; base::WeakPtrFactory<GpuClientImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GpuClientImpl); diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc index 3c8b665a48a..f6d3d4c18f1 100644 --- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc +++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc @@ -16,7 +16,8 @@ GpuDataManager* GpuDataManager::GetInstance() { // static GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() { - return base::Singleton<GpuDataManagerImpl>::get(); + static base::NoDestructor<GpuDataManagerImpl> instance; + return instance.get(); } void GpuDataManagerImpl::BlacklistWebGLForTesting() { @@ -79,16 +80,6 @@ void GpuDataManagerImpl::DisableHardwareAcceleration() { private_->DisableHardwareAcceleration(); } -void GpuDataManagerImpl::BlockSwiftShader() { - base::AutoLock auto_lock(lock_); - private_->BlockSwiftShader(); -} - -bool GpuDataManagerImpl::SwiftShaderAllowed() const { - base::AutoLock auto_lock(lock_); - return private_->SwiftShaderAllowed(); -} - bool GpuDataManagerImpl::HardwareAccelerationEnabled() const { base::AutoLock auto_lock(lock_); return private_->HardwareAccelerationEnabled(); @@ -207,9 +198,14 @@ void GpuDataManagerImpl::NotifyGpuInfoUpdate() { private_->NotifyGpuInfoUpdate(); } -void GpuDataManagerImpl::OnGpuProcessInitFailure() { +gpu::GpuMode GpuDataManagerImpl::GetGpuMode() const { + base::AutoLock auto_lock(lock_); + return private_->GetGpuMode(); +} + +void GpuDataManagerImpl::FallBackToNextGpuMode() { base::AutoLock auto_lock(lock_); - private_->OnGpuProcessInitFailure(); + private_->FallBackToNextGpuMode(); } bool GpuDataManagerImpl::IsGpuProcessUsingHardwareGpu() const { @@ -217,11 +213,14 @@ bool GpuDataManagerImpl::IsGpuProcessUsingHardwareGpu() const { return private_->IsGpuProcessUsingHardwareGpu(); } -GpuDataManagerImpl::GpuDataManagerImpl() - : private_(GpuDataManagerImplPrivate::Create(this)) { +void GpuDataManagerImpl::SetApplicationVisible(bool is_visible) { + base::AutoLock auto_lock(lock_); + private_->SetApplicationVisible(is_visible); } -GpuDataManagerImpl::~GpuDataManagerImpl() { -} +GpuDataManagerImpl::GpuDataManagerImpl() + : private_(std::make_unique<GpuDataManagerImplPrivate>(this)) {} + +GpuDataManagerImpl::~GpuDataManagerImpl() = default; } // namespace content diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h index 06210a34e80..d91d77659f3 100644 --- a/chromium/content/browser/gpu/gpu_data_manager_impl.h +++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h @@ -14,7 +14,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" -#include "base/memory/singleton.h" +#include "base/no_destructor.h" #include "base/process/kill.h" #include "base/synchronization/lock.h" #include "base/time/time.h" @@ -24,6 +24,7 @@ #include "gpu/config/gpu_control_list.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_info.h" +#include "gpu/config/gpu_mode.h" class GURL; @@ -149,44 +150,27 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager { // status update. void NotifyGpuInfoUpdate(); - // Called when GPU process initialization failed. - void OnGpuProcessInitFailure(); + // Return mode describing what the GPU process will be launched to run. + gpu::GpuMode GetGpuMode() const; - void BlockSwiftShader(); - bool SwiftShaderAllowed() const; + // Called when GPU process initialization failed or the GPU process has + // crashed repeatedly. This will try to disable hardware acceleration and then + // SwiftShader WebGL. It will also crash the browser process as a last resort + // on Android and Chrome OS. + void FallBackToNextGpuMode(); // Returns false if the latest GPUInfo gl_renderer is from SwiftShader or // Disabled (in the viz case). bool IsGpuProcessUsingHardwareGpu() const; + // State tracking allows us to customize GPU process launch depending on + // whether we are in the foreground or background. + void SetApplicationVisible(bool is_visible); + private: friend class GpuDataManagerImplPrivate; friend class GpuDataManagerImplPrivateTest; - friend struct base::DefaultSingletonTraits<GpuDataManagerImpl>; - - // It's similar to AutoUnlock, but we want to make it a no-op - // if the owner GpuDataManagerImpl is null. - // This should only be used by GpuDataManagerImplPrivate where - // callbacks are called, during which re-entering - // GpuDataManagerImpl is possible. - class UnlockedSession { - public: - explicit UnlockedSession(GpuDataManagerImpl* owner) - : owner_(owner) { - DCHECK(owner_); - owner_->lock_.AssertAcquired(); - owner_->lock_.Release(); - } - - ~UnlockedSession() { - DCHECK(owner_); - owner_->lock_.Acquire(); - } - - private: - GpuDataManagerImpl* owner_; - DISALLOW_COPY_AND_ASSIGN(UnlockedSession); - }; + friend class base::NoDestructor<GpuDataManagerImpl>; GpuDataManagerImpl(); ~GpuDataManagerImpl() override; diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc index e3b41337158..63797576500 100644 --- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc @@ -32,17 +32,16 @@ #include "content/public/common/content_constants.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" -#include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/config/gpu_blacklist.h" #include "gpu/config/gpu_driver_bug_list.h" #include "gpu/config/gpu_driver_bug_workaround_type.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/config/gpu_info_collector.h" +#include "gpu/config/gpu_preferences.h" #include "gpu/config/gpu_switches.h" #include "gpu/config/gpu_util.h" #include "gpu/config/software_rendering_list_autogen.h" -#include "gpu/ipc/common/gpu_preferences_util.h" #include "gpu/ipc/common/memory_stats.h" #include "gpu/ipc/host/gpu_memory_buffer_support.h" #include "gpu/ipc/host/shader_disk_cache.h" @@ -118,18 +117,21 @@ void UpdateFeatureStats(const gpu::GpuFeatureInfo& gpu_feature_info) { gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING, gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION, + gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION, gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL, gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2}; const std::string kGpuBlacklistFeatureHistogramNames[] = { "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas", "GPU.BlacklistFeatureTestResults.GpuCompositing", "GPU.BlacklistFeatureTestResults.GpuRasterization", + "GPU.BlacklistFeatureTestResults.OopRasterization", "GPU.BlacklistFeatureTestResults.Webgl", "GPU.BlacklistFeatureTestResults.Webgl2"}; const bool kGpuFeatureUserFlags[] = { command_line.HasSwitch(switches::kDisableAccelerated2dCanvas), command_line.HasSwitch(switches::kDisableGpu), command_line.HasSwitch(switches::kDisableGpuRasterization), + command_line.HasSwitch(switches::kDisableOopRasterization), command_line.HasSwitch(switches::kDisableWebGL), (command_line.HasSwitch(switches::kDisableWebGL) || command_line.HasSwitch(switches::kDisableWebGL2))}; @@ -138,6 +140,7 @@ void UpdateFeatureStats(const gpu::GpuFeatureInfo& gpu_feature_info) { "GPU.BlacklistFeatureTestResultsWindows2.Accelerated2dCanvas", "GPU.BlacklistFeatureTestResultsWindows2.GpuCompositing", "GPU.BlacklistFeatureTestResultsWindows2.GpuRasterization", + "GPU.BlacklistFeatureTestResultsWindows2.OopRasterization", "GPU.BlacklistFeatureTestResultsWindows2.Webgl", "GPU.BlacklistFeatureTestResultsWindows2.Webgl2"}; #endif @@ -263,6 +266,35 @@ void UpdateGpuInfoOnIO(const gpu::GPUInfo& gpu_info) { } // anonymous namespace +GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner) + : owner_(owner), + observer_list_(base::MakeRefCounted<GpuDataManagerObserverList>()) { + DCHECK(owner_); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableGpu)) + DisableHardwareAcceleration(); + + if (command_line->HasSwitch(switches::kSingleProcess) || + command_line->HasSwitch(switches::kInProcessGPU)) { + in_process_gpu_ = true; + AppendGpuCommandLine(command_line); + } + +#if defined(OS_MACOSX) + CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_); +#endif // OS_MACOSX + + // For testing only. + if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) + domain_blocking_enabled_ = false; +} + +GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() { +#if defined(OS_MACOSX) + CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_); +#endif +} + void GpuDataManagerImplPrivate::BlacklistWebGLForTesting() { // This function is for testing only, so disable histograms. update_histograms_ = false; @@ -286,8 +318,7 @@ gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfoForHardwareGpu() const { return gpu_info_for_hardware_gpu_; } -bool GpuDataManagerImplPrivate::GpuAccessAllowed( - std::string* reason) const { +bool GpuDataManagerImplPrivate::GpuAccessAllowed(std::string* reason) const { bool swiftshader_available = false; #if BUILDFLAG(ENABLE_SWIFTSHADER) if (!base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -322,8 +353,19 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed( } bool GpuDataManagerImplPrivate::GpuProcessStartAllowed() const { - return base::FeatureList::IsEnabled(features::kVizDisplayCompositor) || - GpuAccessAllowed(nullptr); + if (GpuAccessAllowed(nullptr)) + return true; + +#if defined(USE_X11) || defined(OS_MACOSX) + // If GPU access is disabled with OOP-D we run the display compositor in: + // Browser process: Windows + // GPU process: Linux and Mac + // N/A: Android and Chrome OS (GPU access can't be disabled) + if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) + return true; +#endif + + return false; } void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() { @@ -395,13 +437,11 @@ void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate( } void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) { - GpuDataManagerImpl::UnlockedSession session(owner_); observer_list_->AddObserver(observer); } void GpuDataManagerImplPrivate::RemoveObserver( GpuDataManagerObserver* observer) { - GpuDataManagerImpl::UnlockedSession session(owner_); observer_list_->RemoveObserver(observer); } @@ -514,7 +554,7 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine( gpu::GpuPreferences gpu_prefs = GetGpuPreferencesFromCommandLine(); UpdateGpuPreferences(&gpu_prefs); command_line->AppendSwitchASCII(switches::kGpuPreferences, - gpu::GpuPreferencesToSwitchValue(gpu_prefs)); + gpu_prefs.ToSwitchValue()); std::string use_gl; if (card_disabled_ && SwiftShaderAllowed()) { @@ -560,6 +600,8 @@ void GpuDataManagerImplPrivate::UpdateGpuPreferences( gpu_preferences->texture_target_exception_list = gpu::CreateBufferUsageAndFormatExceptionList(); + + gpu_preferences->watchdog_starts_backgrounded = !application_is_visible_; } void GpuDataManagerImplPrivate::DisableHardwareAcceleration() { @@ -572,11 +614,6 @@ bool GpuDataManagerImplPrivate::HardwareAccelerationEnabled() const { return !card_disabled_; } -void GpuDataManagerImplPrivate::BlockSwiftShader() { - swiftshader_blocked_ = true; - OnGpuBlocked(); -} - bool GpuDataManagerImplPrivate::SwiftShaderAllowed() const { #if !BUILDFLAG(ENABLE_SWIFTSHADER) return false; @@ -613,27 +650,15 @@ void GpuDataManagerImplPrivate::AddLogMessage( void GpuDataManagerImplPrivate::ProcessCrashed( base::TerminationStatus exit_code) { - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - // Unretained is ok, because it's posted to UI thread, the thread - // where the singleton GpuDataManagerImpl lives until the end. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&GpuDataManagerImpl::ProcessCrashed, - base::Unretained(owner_), exit_code)); - return; - } - { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->Notify( - FROM_HERE, &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code); - } + observer_list_->Notify( + FROM_HERE, &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code); } std::unique_ptr<base::ListValue> GpuDataManagerImplPrivate::GetLogMessages() const { auto value = std::make_unique<base::ListValue>(); for (size_t ii = 0; ii < log_messages_.size(); ++ii) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + auto dict = std::make_unique<base::DictionaryValue>(); dict->SetInteger("level", log_messages_[ii].level); dict->SetString("header", log_messages_[ii].header); dict->SetString("message", log_messages_[ii].message); @@ -643,7 +668,7 @@ std::unique_ptr<base::ListValue> GpuDataManagerImplPrivate::GetLogMessages() } void GpuDataManagerImplPrivate::HandleGpuSwitch() { - GpuDataManagerImpl::UnlockedSession session(owner_); + base::AutoUnlock unlock(owner_->lock_); // Notify observers in the browser process. ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched(); // Pass the notification to the GPU process to notify observers there. @@ -701,48 +726,6 @@ void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() { domain_blocking_enabled_ = false; } -// static -GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create( - GpuDataManagerImpl* owner) { - return new GpuDataManagerImplPrivate(owner); -} - -GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner) - : complete_gpu_info_already_requested_(false), - observer_list_(new GpuDataManagerObserverList), - card_disabled_(false), - swiftshader_blocked_(false), - update_histograms_(true), - domain_blocking_enabled_(true), - owner_(owner), - in_process_gpu_(false) { - DCHECK(owner_); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisableGpu)) - DisableHardwareAcceleration(); - - if (command_line->HasSwitch(switches::kSingleProcess) || - command_line->HasSwitch(switches::kInProcessGPU)) { - in_process_gpu_ = true; - AppendGpuCommandLine(command_line); - } - -#if defined(OS_MACOSX) - CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_); -#endif // OS_MACOSX - - // For testing only. - if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) { - domain_blocking_enabled_ = false; - } -} - -GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() { -#if defined(OS_MACOSX) - CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_); -#endif -} - void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() { observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate); } @@ -756,8 +739,11 @@ bool GpuDataManagerImplPrivate::IsGpuProcessUsingHardwareGpu() const { return true; } -std::string GpuDataManagerImplPrivate::GetDomainFromURL( - const GURL& url) const { +void GpuDataManagerImplPrivate::SetApplicationVisible(bool is_visible) { + application_is_visible_ = is_visible; +} + +std::string GpuDataManagerImplPrivate::GetDomainFromURL(const GURL& url) const { // For the moment, we just use the host, or its IP address, as the // entry in the set, rather than trying to figure out the top-level // domain. This does mean that a.foo.com and b.foo.com will be @@ -860,21 +846,44 @@ bool GpuDataManagerImplPrivate::NeedsCompleteGpuInfoCollection() const { #endif } -void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() { +gpu::GpuMode GpuDataManagerImplPrivate::GetGpuMode() const { + if (HardwareAccelerationEnabled()) { + return gpu::GpuMode::HARDWARE_ACCELERATED; + } else if (SwiftShaderAllowed()) { + return gpu::GpuMode::SWIFTSHADER; + } else if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) { + return gpu::GpuMode::DISPLAY_COMPOSITOR; + } else { + return gpu::GpuMode::DISABLED; + } +} + +void GpuDataManagerImplPrivate::FallBackToNextGpuMode() { +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + // Android and Chrome OS can't switch to software compositing. If the GPU + // process initialization fails or GPU process is too unstable then crash the + // browser process to reset everything. + LOG(FATAL) << "GPU process isn't usable. Goodbye."; +#else + // TODO(kylechar): Use GpuMode to store the current mode instead of + // multiple bools. + if (!card_disabled_) { DisableHardwareAcceleration(); - return; - } - if (SwiftShaderAllowed()) { - BlockSwiftShader(); - return; - } - if (!base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) { - // When Viz display compositor is not enabled, if GPU process fails to - // launch with hardware GPU, and then fails to launch with SwiftShader if - // available, then GPU process should not launch again. + } else if (SwiftShaderAllowed()) { + swiftshader_blocked_ = true; + OnGpuBlocked(); + } else if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) { + // The GPU process is frequently crashing with only the display compositor + // running. This should never happen so something is wrong. Crash the + // browser process to reset everything. + LOG(FATAL) << "The display compositor is frequently crashing. Goodbye."; + } else { + // We are already at GpuMode::DISABLED. We shouldn't be launching the GPU + // process for it to fail. NOTREACHED(); } +#endif } } // namespace content diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h index a84efd1a461..68fc14b5286 100644 --- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h +++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h @@ -37,7 +37,8 @@ namespace content { class CONTENT_EXPORT GpuDataManagerImplPrivate { public: - static GpuDataManagerImplPrivate* Create(GpuDataManagerImpl* owner); + explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner); + virtual ~GpuDataManagerImplPrivate(); void BlacklistWebGLForTesting(); gpu::GPUInfo GetGPUInfo() const; @@ -57,7 +58,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate { void UnblockDomainFrom3DAPIs(const GURL& url); void DisableHardwareAcceleration(); bool HardwareAccelerationEnabled() const; - void BlockSwiftShader(); bool SwiftShaderAllowed() const; void UpdateGpuInfo( @@ -99,14 +99,15 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate { bool UpdateActiveGpu(uint32_t vendor_id, uint32_t device_id); - void OnGpuProcessInitFailure(); + gpu::GpuMode GetGpuMode() const; + void FallBackToNextGpuMode(); // Notify all observers whenever there is a GPU info update. void NotifyGpuInfoUpdate(); bool IsGpuProcessUsingHardwareGpu() const; - virtual ~GpuDataManagerImplPrivate(); + void SetApplicationVisible(bool is_visible); private: friend class GpuDataManagerImplPrivateTest; @@ -128,10 +129,10 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate { GpuDataManagerImpl::DomainGuilt last_guilt; }; - typedef std::map<std::string, DomainBlockEntry> DomainBlockMap; + using DomainBlockMap = std::map<std::string, DomainBlockEntry>; - typedef base::ObserverListThreadSafe<GpuDataManagerObserver> - GpuDataManagerObserverList; + using GpuDataManagerObserverList = + base::ObserverListThreadSafe<GpuDataManagerObserver>; struct LogMessage { int level; @@ -146,8 +147,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate { message(_message) { } }; - explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner); - // Called when GPU access (hardware acceleration and swiftshader) becomes // blocked. void OnGpuBlocked(); @@ -170,7 +169,9 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate { // 3) all other platforms, this returns false. bool NeedsCompleteGpuInfoCollection() const; - bool complete_gpu_info_already_requested_; + GpuDataManagerImpl* const owner_; + + bool complete_gpu_info_already_requested_ = false; gpu::GpuFeatureInfo gpu_feature_info_; gpu::GPUInfo gpu_info_; @@ -187,23 +188,23 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate { // Current card force-disabled due to GPU crashes, or disabled through // the --disable-gpu commandline switch. - bool card_disabled_; + bool card_disabled_ = false; // SwiftShader force-blocked due to GPU crashes using SwiftShader. - bool swiftshader_blocked_; + bool swiftshader_blocked_ = false; // We disable histogram stuff in testing, especially in unit tests because // they cause random failures. - bool update_histograms_; + bool update_histograms_ = true; DomainBlockMap blocked_domains_; mutable std::list<base::Time> timestamps_of_gpu_resets_; - bool domain_blocking_enabled_; + bool domain_blocking_enabled_ = true; - GpuDataManagerImpl* owner_; + bool application_is_visible_ = true; // True if --single-process or --in-process-gpu is passed in. - bool in_process_gpu_; + bool in_process_gpu_ = false; DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImplPrivate); }; diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc index a105555d01f..bb1ddc7b334 100644 --- a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc +++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc @@ -21,12 +21,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -#define LONG_STRING_CONST(...) #__VA_ARGS__ - namespace content { namespace { @@ -72,18 +66,14 @@ class GpuDataManagerImplPrivateTest : public testing::Test { // so we can make a little helper class here. class ScopedGpuDataManagerImpl { public: - ScopedGpuDataManagerImpl() : impl_(new GpuDataManagerImpl()) { - EXPECT_TRUE(impl_); - EXPECT_TRUE(impl_->private_.get()); - } - ~ScopedGpuDataManagerImpl() { delete impl_; } - - GpuDataManagerImpl* get() const { return impl_; } + ScopedGpuDataManagerImpl() { EXPECT_TRUE(impl_.private_.get()); } + ~ScopedGpuDataManagerImpl() = default; - GpuDataManagerImpl* operator->() const { return impl_; } + GpuDataManagerImpl* get() { return &impl_; } + GpuDataManagerImpl* operator->() { return &impl_; } private: - GpuDataManagerImpl* impl_; + GpuDataManagerImpl impl_; DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImpl); }; @@ -91,29 +81,17 @@ class GpuDataManagerImplPrivateTest : public testing::Test { // in the GpuDataManagerImpl constructor. class ScopedGpuDataManagerImplPrivate { public: - ScopedGpuDataManagerImplPrivate() : impl_(new GpuDataManagerImpl()) { - EXPECT_TRUE(impl_); - EXPECT_TRUE(impl_->private_.get()); - } - ~ScopedGpuDataManagerImplPrivate() { delete impl_; } + ScopedGpuDataManagerImplPrivate() { EXPECT_TRUE(impl_.private_.get()); } + ~ScopedGpuDataManagerImplPrivate() = default; - GpuDataManagerImplPrivate* get() const { - return impl_->private_.get(); - } - - GpuDataManagerImplPrivate* operator->() const { - return impl_->private_.get(); - } + GpuDataManagerImplPrivate* get() { return impl_.private_.get(); } + GpuDataManagerImplPrivate* operator->() { return impl_.private_.get(); } private: - GpuDataManagerImpl* impl_; + GpuDataManagerImpl impl_; DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImplPrivate); }; - void SetUp() override {} - - void TearDown() override {} - base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager); base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager); void TestBlockingDomainFrom3DAPIs( diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc index 54537e236ac..a64a4419064 100644 --- a/chromium/content/browser/gpu/gpu_internals_ui.cc +++ b/chromium/content/browser/gpu/gpu_internals_ui.cc @@ -64,6 +64,8 @@ namespace { WebUIDataSource* CreateGpuHTMLSource() { WebUIDataSource* source = WebUIDataSource::Create(kChromeUIGpuHost); + source->OverrideContentSecurityPolicyScriptSrc( + "script-src chrome://resources 'self' 'unsafe-eval';"); source->SetJsonPath("strings.js"); source->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS); @@ -147,6 +149,7 @@ std::string GPUDeviceToString(const gpu::GPUInfo::GPUDevice& gpu) { std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue( const gpu::GPUInfo& gpu_info, const gpu::GpuFeatureInfo& gpu_feature_info) { + const gpu::GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu(); auto basic_info = std::make_unique<base::ListValue>(); basic_info->Append(NewDescriptionValuePair( "Initialization time", @@ -158,15 +161,9 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue( "Passthrough Command Decoder", std::make_unique<base::Value>(gpu_info.passthrough_cmd_decoder))); basic_info->Append(NewDescriptionValuePair( - "Direct Composition", - std::make_unique<base::Value>(gpu_info.direct_composition))); - basic_info->Append(NewDescriptionValuePair( - "Supports overlays", - std::make_unique<base::Value>(gpu_info.supports_overlays))); - basic_info->Append(NewDescriptionValuePair( "Sandboxed", std::make_unique<base::Value>(gpu_info.sandboxed))); - basic_info->Append(NewDescriptionValuePair( - "GPU0", GPUDeviceToString(gpu_info.gpu))); + basic_info->Append( + NewDescriptionValuePair("GPU0", GPUDeviceToString(gpu_info.gpu))); for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { basic_info->Append(NewDescriptionValuePair( base::StringPrintf("GPU%d", static_cast<int>(i + 1)), @@ -183,6 +180,22 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue( basic_info->Append( NewDescriptionValuePair("Desktop compositing", compositor)); + basic_info->Append(NewDescriptionValuePair( + "Direct Composition", + std::make_unique<base::Value>(gpu_info.direct_composition))); + basic_info->Append(NewDescriptionValuePair( + "Supports overlays", + std::make_unique<base::Value>(gpu_info.supports_overlays))); + + auto overlay_capabilities = std::make_unique<base::ListValue>(); + for (const auto& cap : gpu_info.overlay_capabilities) { + overlay_capabilities->Append(NewDescriptionValuePair( + gpu::OverlayFormatToString(cap.format), + cap.is_scaling_supported ? "SCALING" : "DIRECT")); + } + basic_info->Append(NewDescriptionValuePair("Overlay capabilities", + std::move(overlay_capabilities))); + std::vector<gfx::PhysicalDisplaySize> display_sizes = gfx::GetPhysicalSizeForDisplays(); for (const auto& display_size : display_sizes) { @@ -208,29 +221,28 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue( #endif basic_info->Append( - NewDescriptionValuePair("Driver vendor", gpu_info.driver_vendor)); - basic_info->Append(NewDescriptionValuePair("Driver version", - gpu_info.driver_version)); - basic_info->Append(NewDescriptionValuePair("Driver date", - gpu_info.driver_date)); + NewDescriptionValuePair("Driver vendor", active_gpu.driver_vendor)); + basic_info->Append( + NewDescriptionValuePair("Driver version", active_gpu.driver_version)); + basic_info->Append( + NewDescriptionValuePair("Driver date", active_gpu.driver_date)); basic_info->Append(NewDescriptionValuePair("Pixel shader version", gpu_info.pixel_shader_version)); basic_info->Append(NewDescriptionValuePair("Vertex shader version", gpu_info.vertex_shader_version)); - basic_info->Append(NewDescriptionValuePair("Max. MSAA samples", - gpu_info.max_msaa_samples)); + basic_info->Append( + NewDescriptionValuePair("Max. MSAA samples", gpu_info.max_msaa_samples)); basic_info->Append(NewDescriptionValuePair("Machine model name", gpu_info.machine_model_name)); basic_info->Append(NewDescriptionValuePair("Machine model version", gpu_info.machine_model_version)); - basic_info->Append(NewDescriptionValuePair("GL_VENDOR", - gpu_info.gl_vendor)); - basic_info->Append(NewDescriptionValuePair("GL_RENDERER", - gpu_info.gl_renderer)); - basic_info->Append(NewDescriptionValuePair("GL_VERSION", - gpu_info.gl_version)); - basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS", - gpu_info.gl_extensions)); + basic_info->Append(NewDescriptionValuePair("GL_VENDOR", gpu_info.gl_vendor)); + basic_info->Append( + NewDescriptionValuePair("GL_RENDERER", gpu_info.gl_renderer)); + basic_info->Append( + NewDescriptionValuePair("GL_VERSION", gpu_info.gl_version)); + basic_info->Append( + NewDescriptionValuePair("GL_EXTENSIONS", gpu_info.gl_extensions)); basic_info->Append(NewDescriptionValuePair( "Disabled Extensions", gpu_feature_info.disabled_extensions)); basic_info->Append(NewDescriptionValuePair( @@ -242,8 +254,8 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue( basic_info->Append(NewDescriptionValuePair("Window system binding extensions", gpu_info.gl_ws_extensions)); #if defined(USE_X11) - basic_info->Append(NewDescriptionValuePair("Window manager", - ui::GuessWindowManagerName())); + basic_info->Append( + NewDescriptionValuePair("Window manager", ui::GuessWindowManagerName())); { std::unique_ptr<base::Environment> env(base::Environment::Create()); std::string value; @@ -264,8 +276,8 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue( std::string reset_strategy = base::StringPrintf("0x%04x", gpu_info.gl_reset_notification_strategy); - basic_info->Append(NewDescriptionValuePair( - "Reset notification strategy", reset_strategy)); + basic_info->Append( + NewDescriptionValuePair("Reset notification strategy", reset_strategy)); basic_info->Append(NewDescriptionValuePair( "GPU process crash count", @@ -436,8 +448,12 @@ std::string GetProfileName(gpu::VideoCodecProfile profile) { return "dolby vision profile 7"; case gpu::THEORAPROFILE_ANY: return "theora"; - case gpu::AV1PROFILE_PROFILE0: - return "av1 profile0"; + case gpu::AV1PROFILE_PROFILE_MAIN: + return "av1 profile main"; + case gpu::AV1PROFILE_PROFILE_HIGH: + return "av1 profile high"; + case gpu::AV1PROFILE_PROFILE_PRO: + return "av1 profile pro"; } NOTREACHED(); return ""; diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc index 72708d0f0c7..bdecceea7e6 100644 --- a/chromium/content/browser/gpu/gpu_process_host.cc +++ b/chromium/content/browser/gpu/gpu_process_host.cc @@ -15,6 +15,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/debug/alias.h" #include "base/feature_list.h" #include "base/logging.h" #include "base/macros.h" @@ -23,6 +24,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" @@ -34,14 +36,17 @@ #include "components/viz/common/switches.h" #include "content/browser/browser_child_process_host_impl.h" #include "content/browser/browser_main_loop.h" +#include "content/browser/compositor/image_transport_factory.h" #include "content/browser/field_trial_recorder.h" #include "content/browser/gpu/compositor_util.h" #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/gpu/gpu_main_thread_factory.h" #include "content/browser/gpu/shader_cache_factory.h" +#include "content/browser/memory/memory_coordinator_impl.h" #include "content/browser/service_manager/service_manager_context.h" #include "content/common/child_process_host_impl.h" #include "content/common/in_process_child_thread_params.h" +#include "content/common/memory_coordinator.mojom.h" #include "content/common/service_manager/child_connection.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_thread.h" @@ -55,14 +60,14 @@ #include "content/public/common/sandboxed_process_launcher_delegate.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" -#include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/config/gpu_driver_bug_list.h" #include "gpu/config/gpu_driver_bug_workaround_type.h" +#include "gpu/config/gpu_preferences.h" #include "gpu/ipc/host/shader_disk_cache.h" +#include "gpu/ipc/in_process_command_buffer.h" #include "media/base/media_switches.h" #include "media/media_buildflags.h" -#include "mojo/edk/embedder/embedder.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -73,6 +78,7 @@ #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/display/display_switches.h" +#include "ui/gfx/font_render_params.h" #include "ui/gfx/switches.h" #include "ui/gl/gl_switches.h" #include "ui/latency/latency_info.h" @@ -104,18 +110,35 @@ #include "gpu/ipc/common/gpu_surface_tracker.h" #endif +#if defined(OS_MACOSX) +#include "content/browser/gpu/ca_transaction_gpu_coordinator.h" +#endif + namespace content { base::subtle::Atomic32 GpuProcessHost::gpu_crash_count_ = 0; -int GpuProcessHost::gpu_recent_crash_count_ = 0; bool GpuProcessHost::crashed_before_ = false; -int GpuProcessHost::swiftshader_crash_count_ = 0; +int GpuProcessHost::hardware_accelerated_recent_crash_count_ = 0; int GpuProcessHost::swiftshader_recent_crash_count_ = 0; -int GpuProcessHost::display_compositor_crash_count_ = 0; int GpuProcessHost::display_compositor_recent_crash_count_ = 0; namespace { +// UMA histogram names. +constexpr char kProcessLifetimeEventsHardwareAccelerated[] = + "GPU.ProcessLifetimeEvents.HardwareAccelerated"; +constexpr char kProcessLifetimeEventsSwiftShader[] = + "GPU.ProcessLifetimeEvents.SwiftShader"; +constexpr char kProcessLifetimeEventsDisplayCompositor[] = + "GPU.ProcessLifetimeEvents.DisplayCompositor"; + +// Forgive one GPU process crash after this many minutes. +constexpr int kForgiveGpuCrashMinutes = 60; + +// Forgive one GPU process crash, when the GPU process is launched to run only +// the display compositor, after this many minutes. +constexpr int kForgiveDisplayCompositorCrashMinutes = 10; + // This matches base::TerminationStatus. // These values are persisted to logs. Entries (except MAX_ENUM) should not be // renumbered and numeric values should never be reused. Should also avoid @@ -185,19 +208,21 @@ static const char* const kSwitchNames[] = { switches::kDisableGLExtensions, switches::kDisableLogging, switches::kDisableShaderNameHashing, + switches::kDisableSkiaRuntimeOpts, switches::kDisableWebRtcHWEncoding, #if defined(OS_WIN) switches::kEnableAcceleratedVpxDecode, #endif switches::kEnableGpuRasterization, switches::kEnableLogging, - switches::kEnableOOPRasterization, switches::kEnableVizDevTools, switches::kHeadless, switches::kLoggingLevel, switches::kEnableLowEndDeviceMode, switches::kDisableLowEndDeviceMode, switches::kRunAllCompositorStagesBeforeDraw, + switches::kSkiaFontCacheLimitMb, + switches::kSkiaResourceCacheLimitMb, switches::kTestGLLib, switches::kTraceToConsole, switches::kUseFakeJpegDecodeAccelerator, @@ -226,15 +251,19 @@ static const char* const kSwitchNames[] = { #if defined(OS_ANDROID) switches::kOrderfileMemoryOptimization, #endif + switches::kWebglAntialiasingMode, + switches::kWebglMSAASampleCount, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum GPUProcessLifetimeEvent { - LAUNCHED, - DIED_FIRST_TIME, - DIED_SECOND_TIME, - DIED_THIRD_TIME, - DIED_FOURTH_TIME, - GPU_PROCESS_LIFETIME_EVENT_MAX = 100 + LAUNCHED = 0, + // When the GPU process crashes the (DIED_FIRST_TIME + recent_crash_count - 1) + // bucket in the appropriate UMA histogram will be incremented. The first + // crash will be DIED_FIRST_TIME, the second DIED_FIRST_TIME+1, etc. + DIED_FIRST_TIME = 1, + GPU_PROCESS_LIFETIME_EVENT_MAX = 100, }; // Indexed by GpuProcessKind. There is one of each kind maximum. This array may @@ -442,7 +471,7 @@ void BindDiscardableMemoryRequestOnUI( DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(USE_AURA) - if (features::IsMashEnabled()) { + if (!features::IsAshInBrowserProcess()) { ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( ui::mojom::kServiceName, std::move(request)); return; @@ -455,11 +484,28 @@ void BindDiscardableMemoryRequestOnUI( BrowserMainLoop::GetInstance()->discardable_shared_memory_manager())); } +struct FontRenderParamsOnIO { + bool initialized = false; + gfx::FontRenderParams params; +}; + +FontRenderParamsOnIO& GetFontRenderParamsOnIO() { + static base::NoDestructor<FontRenderParamsOnIO> instance; + return *instance; +} + +void CreateMemoryCoordinatorHandleForGpuProcess( + int gpu_process_id, + mojom::MemoryCoordinatorHandleRequest request) { + MemoryCoordinatorImpl::GetInstance()->CreateHandle(gpu_process_id, + std::move(request)); +} + } // anonymous namespace class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter { public: - ConnectionFilterImpl() { + explicit ConnectionFilterImpl(int gpu_process_id) { auto task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::UI); registry_.AddInterface(base::Bind(&FieldTrialRecorder::Create), task_runner); @@ -468,6 +514,11 @@ class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter { base::Bind(&BindJavaInterface<media::mojom::AndroidOverlayProvider>), task_runner); #endif + + registry_.AddInterface( + base::BindRepeating(&CreateMemoryCoordinatorHandleForGpuProcess, + gpu_process_id), + task_runner); } private: @@ -488,6 +539,16 @@ class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter { }; // static +void GpuProcessHost::InitFontRenderParamsOnIO( + const gfx::FontRenderParams& params) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(!GetFontRenderParamsOnIO().initialized); + + GetFontRenderParamsOnIO().initialized = true; + GetFontRenderParamsOnIO().params = params; +} + +// static bool GpuProcessHost::ValidateHost(GpuProcessHost* host) { // The Gpu process is invalid if it's not using SwiftShader, the card is // blacklisted, and we can kill it and start over. @@ -612,17 +673,20 @@ int GpuProcessHost::GetGpuCrashCount() { } // static -void GpuProcessHost::IncrementCrashCount(int* crash_count) { +void GpuProcessHost::IncrementCrashCount(int forgive_minutes, + int* crash_count) { + DCHECK_GT(forgive_minutes, 0); + // Last time the process crashed. - static base::Time last_crash_time; + static base::TimeTicks last_crash_time; - // Allow about 1 crash per hour to be removed from the crash count, so very - // occasional crashes won't eventually add up and prevent the process from - // launching. - base::Time current_time = base::Time::Now(); + // Remove one crash per |forgive_minutes| from the crash count, so occasional + // crashes won't add up and eventually prevent using the GPU process. + base::TimeTicks current_time = base::TimeTicks::Now(); if (crashed_before_) { - int hours_different = (current_time - last_crash_time).InHours(); - *crash_count = std::max(0, *crash_count - hours_different); + int minutes_delta = (current_time - last_crash_time).InMinutes(); + int crashes_to_forgive = minutes_delta / forgive_minutes; + *crash_count = std::max(0, *crash_count - crashes_to_forgive); } ++(*crash_count); @@ -663,6 +727,13 @@ GpuProcessHost::~GpuProcessHost() { SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID); +#if defined(OS_MACOSX) + if (ca_transaction_gpu_coordinator_) { + ca_transaction_gpu_coordinator_->HostWillBeDestroyed(); + ca_transaction_gpu_coordinator_ = nullptr; + } +#endif + if (status_ == UNKNOWN) { RunRequestGPUInfoCallbacks(gpu::GPUInfo()); } else { @@ -806,11 +877,14 @@ bool GpuProcessHost::Init() { // May be null during test execution. if (ServiceManagerConnection::GetForProcess()) { ServiceManagerConnection::GetForProcess()->AddConnectionFilter( - std::make_unique<ConnectionFilterImpl>()); + std::make_unique<ConnectionFilterImpl>(process_->GetData().id)); } process_->GetHost()->CreateChannelMojo(); + mode_ = GpuDataManagerImpl::GetInstance()->GetGpuMode(); + DCHECK_NE(mode_, gpu::GpuMode::DISABLED); + if (in_process_) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(GetGpuMainThreadFactory()); @@ -819,7 +893,7 @@ bool GpuProcessHost::Init() { in_process_gpu_thread_.reset(GetGpuMainThreadFactory()( InProcessChildThreadParams( base::ThreadTaskRunnerHandle::Get(), - process_->GetInProcessBrokerClientInvitation(), + process_->GetInProcessMojoInvitation(), process_->child_connection()->service_token()), gpu_preferences)); base::Thread::Options options; @@ -850,14 +924,20 @@ bool GpuProcessHost::Init() { base::BindOnce(&BindDiscardableMemoryRequestOnUI, std::move(discardable_request))); + DCHECK(GetFontRenderParamsOnIO().initialized); gpu_main_ptr_->CreateGpuService( mojo::MakeRequest(&gpu_service_ptr_), std::move(host_proxy), - std::move(discardable_manager_ptr), activity_flags_.CloneHandle()); + std::move(discardable_manager_ptr), activity_flags_.CloneHandle(), + GetFontRenderParamsOnIO().params.subpixel_rendering); #if defined(USE_OZONE) InitOzone(); #endif // defined(USE_OZONE) +#if defined(OS_MACOSX) + ca_transaction_gpu_coordinator_ = CATransactionGPUCoordinator::Create(this); +#endif + return true; } @@ -916,6 +996,16 @@ void GpuProcessHost::EstablishGpuChannel( return; } + bool oopd_enabled = + base::FeatureList::IsEnabled(features::kVizDisplayCompositor); + if (oopd_enabled && client_id == gpu::InProcessCommandBuffer::kGpuClientId) { + // The display-compositor in the gpu process uses this special client id. + callback.Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(), + gpu::GpuFeatureInfo(), + EstablishChannelStatus::GPU_ACCESS_DENIED); + return; + } + DCHECK_EQ(preempts, allow_view_command_buffers); DCHECK_EQ(preempts, allow_real_time_streams); bool is_gpu_host = preempts; @@ -929,6 +1019,8 @@ void GpuProcessHost::EstablishGpuChannel( if (!base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGpuShaderDiskCache)) { CreateChannelCache(client_id); + if (oopd_enabled) + CreateChannelCache(gpu::InProcessCommandBuffer::kGpuClientId); } } @@ -987,19 +1079,6 @@ void GpuProcessHost::RequestHDRStatus(RequestHDRStatusCallback request_cb) { gpu_service_ptr_->RequestHDRStatus(std::move(request_cb)); } -#if defined(OS_ANDROID) -void GpuProcessHost::SendDestroyingVideoSurface(int surface_id, - const base::Closure& done_cb) { - TRACE_EVENT0("gpu", "GpuProcessHost::SendDestroyingVideoSurface"); - DCHECK(send_destroying_video_surface_done_cb_.is_null()); - DCHECK(!done_cb.is_null()); - send_destroying_video_surface_done_cb_ = done_cb; - gpu_service_ptr_->DestroyingVideoSurface( - surface_id, base::Bind(&GpuProcessHost::OnDestroyingVideoSurfaceAck, - weak_ptr_factory_.GetWeakPtr())); -} -#endif - void GpuProcessHost::OnChannelEstablished( int client_id, const EstablishChannelCallback& callback, @@ -1029,13 +1108,13 @@ void GpuProcessHost::OnChannelEstablished( } void GpuProcessHost::OnGpuMemoryBufferCreated( - const gfx::GpuMemoryBufferHandle& handle) { + gfx::GpuMemoryBufferHandle handle) { TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryBufferCreated"); DCHECK(!create_gpu_memory_buffer_requests_.empty()); auto callback = std::move(create_gpu_memory_buffer_requests_.front()); create_gpu_memory_buffer_requests_.pop(); - std::move(callback).Run(handle, BufferCreationStatus::SUCCESS); + std::move(callback).Run(std::move(handle), BufferCreationStatus::SUCCESS); } #if defined(OS_ANDROID) @@ -1056,6 +1135,11 @@ void GpuProcessHost::OnProcessLaunched() { } void GpuProcessHost::OnProcessLaunchFailed(int error_code) { + // TODO(crbug.com/849639): Ensure |error_code| is included in crash minidumps. + // This is for debugging and should be removed when bug is closed. + int process_launch_error_code = error_code; + base::debug::Alias(&process_launch_error_code); + #if defined(OS_WIN) if (kind_ == GPU_PROCESS_KIND_SANDBOXED) RecordAppContainerStatus(error_code, crashed_before_); @@ -1064,6 +1148,14 @@ void GpuProcessHost::OnProcessLaunchFailed(int error_code) { } void GpuProcessHost::OnProcessCrashed(int exit_code) { + // TODO(crbug.com/849639): Ensure |exit_code| is included in crash minidumps. + // This is for debugging and should be removed when bug is closed. + int process_crash_exit_code = exit_code; + base::debug::Alias(&process_crash_exit_code); + + // Record crash before doing anything that could start a new GPU process. + RecordProcessCrash(); + // If the GPU process crashed while compiling a shader, we may have invalid // cached binaries. Completely clear the shader cache to force shader binaries // to be re-created. @@ -1079,7 +1171,6 @@ void GpuProcessHost::OnProcessCrashed(int exit_code) { } } SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID); - RecordProcessCrash(); ChildProcessTerminationInfo info = process_->GetTerminationInfo(true /* known_dead */); @@ -1117,7 +1208,8 @@ void GpuProcessHost::DidFailInitialize() { UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", false); status_ = FAILURE; GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); - gpu_data_manager->OnGpuProcessInitFailure(); + if (kind_ == GPU_PROCESS_KIND_SANDBOXED) + gpu_data_manager->FallBackToNextGpuMode(); RunRequestGPUInfoCallbacks(gpu_data_manager->GetGPUInfo()); } @@ -1126,7 +1218,7 @@ void GpuProcessHost::DidCreateContextSuccessfully() { // Android may kill the GPU process to free memory, especially when the app // is the background, so Android cannot have a hard limit on GPU starts. // Reset crash count on Android when context creation succeeds. - gpu_recent_crash_count_ = 0; + hardware_accelerated_recent_crash_count_ = 0; #endif } @@ -1193,6 +1285,18 @@ void GpuProcessHost::DidLoseContext(bool offscreen, GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(active_url, guilt); } +void GpuProcessHost::DisableGpuCompositing() { +#if !defined(OS_ANDROID) + // TODO(crbug.com/819474): The switch from GPU to software compositing should + // be handled here instead of by ImageTransportFactory. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, base::BindOnce([]() { + if (auto* factory = ImageTransportFactory::GetInstance()) + factory->DisableGpuCompositing(); + })); +#endif +} + void GpuProcessHost::SetChildSurface(gpu::SurfaceHandle parent_handle, gpu::SurfaceHandle window_handle) { #if defined(OS_WIN) @@ -1317,6 +1421,8 @@ bool GpuProcessHost::LaunchGpuProcess() { GetContentClient()->browser()->AppendExtraCommandLineSwitches( cmd_line.get(), process_->GetData().id); + // TODO(kylechar): The command line flags added here should be based on + // |mode_|. GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line.get()); bool swiftshader_rendering = (cmd_line->GetSwitchValueASCII(switches::kUseGL) == @@ -1338,8 +1444,19 @@ bool GpuProcessHost::LaunchGpuProcess() { process_->Launch(std::move(delegate), std::move(cmd_line), true); process_launched_ = true; - UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", - LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); + if (kind_ == GPU_PROCESS_KIND_SANDBOXED) { + if (mode_ == gpu::GpuMode::HARDWARE_ACCELERATED) { + UMA_HISTOGRAM_ENUMERATION(kProcessLifetimeEventsHardwareAccelerated, + LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); + } else if (mode_ == gpu::GpuMode::SWIFTSHADER) { + UMA_HISTOGRAM_ENUMERATION(kProcessLifetimeEventsSwiftShader, LAUNCHED, + GPU_PROCESS_LIFETIME_EVENT_MAX); + } else if (mode_ == gpu::GpuMode::DISPLAY_COMPOSITOR) { + UMA_HISTOGRAM_ENUMERATION(kProcessLifetimeEventsDisplayCompositor, + LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); + } + } + return true; } @@ -1384,89 +1501,85 @@ void GpuProcessHost::BlockLiveOffscreenContexts() { } void GpuProcessHost::RecordProcessCrash() { -#if !defined(OS_ANDROID) - // Maximum number of times the GPU process is allowed to crash in a session. - // Once this limit is reached, any request to launch the GPU process will - // fail. - const int kGpuMaxCrashCount = 3; +#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) + // Maximum number of times the GPU process can crash before we try something + // different, like disabling hardware acceleration or all GL. + constexpr int kGpuFallbackCrashCount = 3; #else - // On android there is no way to recover without gpu, and the OS can kill the - // gpu process arbitrarily, so use a higher count to allow for that. - const int kGpuMaxCrashCount = 6; + // Android and Chrome OS switch to software compositing and fallback crashes + // the browser process. For Android the OS can also kill the GPU process + // arbitrarily. Use a larger maximum crash count here. + constexpr int kGpuFallbackCrashCount = 6; #endif - bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGpuProcessCrashLimit); - // Ending only acts as a failure if the GPU process was actually started and // was intended for actual rendering (and not just checking caps or other // options). - if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) { - if (GpuDataManagerImpl::GetInstance()->HardwareAccelerationEnabled()) { - int count = static_cast<int>( - base::subtle::NoBarrier_AtomicIncrement(&gpu_crash_count_, 1)); - UMA_HISTOGRAM_EXACT_LINEAR( - "GPU.GPUProcessLifetimeEvents", - std::min(DIED_FIRST_TIME + count, GPU_PROCESS_LIFETIME_EVENT_MAX - 1), - static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX)); - - IncrementCrashCount(&gpu_recent_crash_count_); - if ((gpu_recent_crash_count_ >= kGpuMaxCrashCount || - status_ == FAILURE) && - !disable_crash_limit) { -#if defined(OS_ANDROID) - // Android can not fall back to software. If things are too unstable - // then we just crash chrome to reset everything. Sorry. - LOG(FATAL) << "Unable to start gpu process, giving up."; -#elif defined(OS_CHROMEOS) - // ChromeOS also can not fall back to software. There we will just - // keep retrying to make the gpu process forever. Good luck. - DLOG(ERROR) << "Gpu process is unstable and crashing repeatedly, if " - "you didn't notice already."; -#else - // The GPU process is too unstable to use. Disable it for current - // session. - GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration(); -#endif - } - } else if (GpuDataManagerImpl::GetInstance()->SwiftShaderAllowed()) { - UMA_HISTOGRAM_EXACT_LINEAR( - "GPU.SwiftShaderLifetimeEvents", - DIED_FIRST_TIME + swiftshader_crash_count_, - static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX)); - ++swiftshader_crash_count_; - - IncrementCrashCount(&swiftshader_recent_crash_count_); - if (swiftshader_recent_crash_count_ >= kGpuMaxCrashCount && - !disable_crash_limit) { - // SwiftShader is too unstable to use. Disable it for current session. - GpuDataManagerImpl::GetInstance()->BlockSwiftShader(); - } - } else { - UMA_HISTOGRAM_EXACT_LINEAR( - "GPU.DisplayCompositorLifetimeEvents", - DIED_FIRST_TIME + display_compositor_crash_count_, - static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX)); - ++display_compositor_crash_count_; - - IncrementCrashCount(&display_compositor_recent_crash_count_); - if (display_compositor_recent_crash_count_ >= kGpuMaxCrashCount && - !disable_crash_limit) { - // Viz display compositor is too unstable. Crash chrome to reset - // everything. - LOG(FATAL) << "Unable to start viz process, giving up."; - } - } + if (!process_launched_ || kind_ != GPU_PROCESS_KIND_SANDBOXED) + return; + + // Keep track of the total number of GPU crashes. + base::subtle::NoBarrier_AtomicIncrement(&gpu_crash_count_, 1); + + int recent_crash_count = 0; + if (mode_ == gpu::GpuMode::HARDWARE_ACCELERATED) { + IncrementCrashCount(kForgiveGpuCrashMinutes, + &hardware_accelerated_recent_crash_count_); + UMA_HISTOGRAM_EXACT_LINEAR( + kProcessLifetimeEventsHardwareAccelerated, + DIED_FIRST_TIME + hardware_accelerated_recent_crash_count_ - 1, + static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX)); + recent_crash_count = hardware_accelerated_recent_crash_count_; + } else if (mode_ == gpu::GpuMode::SWIFTSHADER) { + IncrementCrashCount(kForgiveGpuCrashMinutes, + &swiftshader_recent_crash_count_); + UMA_HISTOGRAM_EXACT_LINEAR( + kProcessLifetimeEventsSwiftShader, + DIED_FIRST_TIME + swiftshader_recent_crash_count_ - 1, + static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX)); + recent_crash_count = swiftshader_recent_crash_count_; + } else if (mode_ == gpu::GpuMode::DISPLAY_COMPOSITOR) { + IncrementCrashCount(kForgiveDisplayCompositorCrashMinutes, + &display_compositor_recent_crash_count_); + UMA_HISTOGRAM_EXACT_LINEAR( + kProcessLifetimeEventsDisplayCompositor, + DIED_FIRST_TIME + display_compositor_recent_crash_count_ - 1, + static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX)); + recent_crash_count = display_compositor_recent_crash_count_; } + + // TODO(crbug.com/849639): Ensure crash counts are included in crash + // minidumps. This is for debugging and should be removed when bug is closed. + int hardware_accelerated_crash_count = + hardware_accelerated_recent_crash_count_; + base::debug::Alias(&hardware_accelerated_crash_count); + int swiftshader_crash_count = swiftshader_recent_crash_count_; + base::debug::Alias(&swiftshader_crash_count); + int display_compositor_crash_count = display_compositor_recent_crash_count_; + base::debug::Alias(&display_compositor_crash_count); + + // GPU process initialization failed and fallback already happened. + if (status_ == FAILURE) + return; + + bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableGpuProcessCrashLimit); + + // GPU process crashed too many times, fallback on a different GPU process + // mode. + if (recent_crash_count >= kGpuFallbackCrashCount && !disable_crash_limit) + GpuDataManagerImpl::GetInstance()->FallBackToNextGpuMode(); } std::string GpuProcessHost::GetShaderPrefixKey() { if (shader_prefix_key_.empty()) { - gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo(); + const gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo(); + const gpu::GPUInfo::GPUDevice& active_gpu = info.active_gpu(); shader_prefix_key_ = GetContentClient()->GetProduct() + "-" + info.gl_vendor + "-" + info.gl_renderer + "-" + - info.driver_version + "-" + info.driver_vendor; + active_gpu.driver_version + "-" + + active_gpu.driver_vendor; #if defined(OS_ANDROID) std::string build_fp = @@ -1511,4 +1624,8 @@ void GpuProcessHost::CreateChannelCache(int32_t client_id) { client_id_to_shader_cache_[client_id] = cache; } +int GpuProcessHost::GetIDForTesting() const { + return process_->GetData().id; +} + } // namespace content diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h index e08bcf72fc1..3ca9cf5c561 100644 --- a/chromium/content/browser/gpu/gpu_process_host.h +++ b/chromium/content/browser/gpu/gpu_process_host.h @@ -28,6 +28,7 @@ #include "gpu/command_buffer/common/constants.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_info.h" +#include "gpu/config/gpu_mode.h" #include "gpu/ipc/common/surface_handle.h" #include "ipc/ipc_sender.h" #include "mojo/public/cpp/bindings/binding.h" @@ -43,6 +44,10 @@ namespace base { class Thread; } +namespace gfx { +struct FontRenderParams; +} + namespace gpu { class ShaderDiskCache; struct SyncToken; @@ -51,6 +56,10 @@ struct SyncToken; namespace content { class BrowserChildProcessHostImpl; +#if defined(OS_MACOSX) +class CATransactionGPUCoordinator; +#endif + class GpuProcessHost : public BrowserChildProcessHostDelegate, public IPC::Sender, public viz::mojom::GpuHost { @@ -80,7 +89,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, SUCCESS, }; using CreateGpuMemoryBufferCallback = - base::OnceCallback<void(const gfx::GpuMemoryBufferHandle& handle, + base::OnceCallback<void(gfx::GpuMemoryBufferHandle handle, BufferCreationStatus status)>; using RequestGPUInfoCallback = base::Callback<void(const gpu::GPUInfo&)>; @@ -110,6 +119,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, bool force_create, const base::Callback<void(GpuProcessHost*)>& callback); + static void InitFontRenderParamsOnIO(const gfx::FontRenderParams& params); + void BindInterface(const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe); @@ -155,12 +166,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, void RequestGPUInfo(RequestGPUInfoCallback request_cb); void RequestHDRStatus(RequestHDRStatusCallback request_cb); -#if defined(OS_ANDROID) - // Tells the GPU process that the given surface is being destroyed so that it - // can stop using it. - void SendDestroyingVideoSurface(int surface_id, const base::Closure& done_cb); -#endif - // What kind of GPU process, e.g. sandboxed or unsandboxed. GpuProcessKind kind(); @@ -175,6 +180,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, return wake_up_gpu_before_drawing_; } + CONTENT_EXPORT int GetIDForTesting() const; + private: class ConnectionFilterImpl; @@ -182,9 +189,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, static bool ValidateHost(GpuProcessHost* host); - // Increments the given crash count. Also, for each hour passed since the - // previous crash, removes an old crash from the count. - static void IncrementCrashCount(int* crash_count); + // Increments |crash_count| by one. Before incrementing |crash_count|, for + // each |forgive_minutes| that has passed since the previous crash remove one + // old crash. + static void IncrementCrashCount(int forgive_minutes, int* crash_count); GpuProcessHost(int host_id, GpuProcessKind kind); ~GpuProcessHost() override; @@ -217,6 +225,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, void DidLoseContext(bool offscreen, gpu::error::ContextLostReason reason, const GURL& active_url) override; + void DisableGpuCompositing() override; void SetChildSurface(gpu::SurfaceHandle parent, gpu::SurfaceHandle child) override; void StoreShaderToDisk(int32_t client_id, @@ -229,7 +238,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, void OnChannelEstablished(int client_id, const EstablishChannelCallback& callback, mojo::ScopedMessagePipeHandle channel_handle); - void OnGpuMemoryBufferCreated(const gfx::GpuMemoryBufferHandle& handle); + void OnGpuMemoryBufferCreated(gfx::GpuMemoryBufferHandle handle); // Message handlers. #if defined(OS_ANDROID) @@ -279,6 +288,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, GpuProcessKind kind_; + gpu::GpuMode mode_ = gpu::GpuMode::UNKNOWN; + // Whether we actually launched a GPU process. bool process_launched_; @@ -287,12 +298,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, // Time Init started. Used to log total GPU process startup time to UMA. base::TimeTicks init_start_time_; + // The total number of GPU process crashes. static base::subtle::Atomic32 gpu_crash_count_; - static int gpu_recent_crash_count_; static bool crashed_before_; - static int swiftshader_crash_count_; + static int hardware_accelerated_recent_crash_count_; static int swiftshader_recent_crash_count_; - static int display_compositor_crash_count_; static int display_compositor_recent_crash_count_; // Here the bottom-up destruction order matters: @@ -302,6 +312,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, std::unique_ptr<BrowserChildProcessHostImpl> process_; std::unique_ptr<base::Thread> in_process_gpu_thread_; +#if defined(OS_MACOSX) + scoped_refptr<CATransactionGPUCoordinator> ca_transaction_gpu_coordinator_; +#endif + // Track the URLs of the pages which have live offscreen contexts, // assumed to be associated with untrusted content such as WebGL. // For best robustness, when any context lost notification is |