| // Copyright 2016 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 "services/ws/gpu_host/gpu_host.h" |
| |
| #include "base/command_line.h" |
| #include "base/memory/shared_memory.h" |
| #include "base/run_loop.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "components/discardable_memory/service/discardable_shared_memory_manager.h" |
| #include "components/viz/common/frame_sinks/begin_frame_source.h" |
| #include "components/viz/common/switches.h" |
| #include "components/viz/host/gpu_client.h" |
| #include "components/viz/host/gpu_client_delegate.h" |
| #include "components/viz/host/host_gpu_memory_buffer_manager.h" |
| #include "components/viz/service/main/viz_main_impl.h" |
| #include "gpu/command_buffer/service/gpu_switches.h" |
| #include "gpu/config/gpu_preferences.h" |
| #include "gpu/ipc/client/gpu_channel_host.h" |
| #include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h" |
| #include "gpu/ipc/common/gpu_memory_buffer_support.h" |
| #include "gpu/ipc/host/shader_disk_cache.h" |
| #include "gpu/ipc/service/gpu_init.h" |
| #include "media/gpu/buildflags.h" |
| #include "mojo/public/cpp/bindings/strong_binding.h" |
| #include "mojo/public/cpp/system/buffer.h" |
| #include "mojo/public/cpp/system/platform_handle.h" |
| #include "services/service_manager/public/cpp/connector.h" |
| #include "services/viz/privileged/interfaces/viz_main.mojom.h" |
| #include "services/viz/public/interfaces/constants.mojom.h" |
| #include "services/ws/gpu_host/gpu_host_delegate.h" |
| #include "ui/base/ui_base_features.h" |
| #include "ui/gfx/buffer_format_util.h" |
| |
| #if defined(OS_WIN) |
| #include "ui/gfx/win/rendering_window_manager.h" |
| #endif |
| |
| #if defined(OS_CHROMEOS) |
| #include "services/ws/gpu_host/arc_client.h" |
| #endif |
| |
| #if defined(OS_CHROMEOS) && BUILDFLAG(USE_VAAPI) |
| #include "media/gpu/vaapi/vaapi_wrapper.h" |
| #endif |
| |
| namespace ws { |
| namespace gpu_host { |
| |
| namespace { |
| |
| // The client Id 1 is reserved for the frame sink manager. |
| const int32_t kInternalGpuChannelClientId = 2; |
| |
| class GpuClientDelegate : public viz::GpuClientDelegate { |
| public: |
| GpuClientDelegate(viz::GpuHostImpl* gpu_host_impl, |
| viz::HostGpuMemoryBufferManager* gpu_memory_buffer_manager); |
| ~GpuClientDelegate() override; |
| |
| // viz::GpuClientDelegate: |
| viz::GpuHostImpl* EnsureGpuHost() override; |
| viz::HostGpuMemoryBufferManager* GetGpuMemoryBufferManager() override; |
| |
| private: |
| viz::GpuHostImpl* gpu_host_impl_; |
| viz::HostGpuMemoryBufferManager* gpu_memory_buffer_manager_; |
| |
| DISALLOW_COPY_AND_ASSIGN(GpuClientDelegate); |
| }; |
| |
| GpuClientDelegate::GpuClientDelegate( |
| viz::GpuHostImpl* gpu_host_impl, |
| viz::HostGpuMemoryBufferManager* gpu_memory_buffer_manager) |
| : gpu_host_impl_(gpu_host_impl), |
| gpu_memory_buffer_manager_(gpu_memory_buffer_manager) {} |
| |
| GpuClientDelegate::~GpuClientDelegate() = default; |
| |
| viz::GpuHostImpl* GpuClientDelegate::EnsureGpuHost() { |
| return gpu_host_impl_; |
| } |
| |
| viz::HostGpuMemoryBufferManager* |
| GpuClientDelegate::GetGpuMemoryBufferManager() { |
| return gpu_memory_buffer_manager_; |
| } |
| |
| } // namespace |
| |
| GpuHost::GpuHost(GpuHostDelegate* delegate, |
| service_manager::Connector* connector, |
| discardable_memory::DiscardableSharedMemoryManager* |
| discardable_shared_memory_manager) |
| : delegate_(delegate), |
| discardable_shared_memory_manager_(discardable_shared_memory_manager), |
| next_client_id_(kInternalGpuChannelClientId + 1), |
| main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| gpu_thread_("GpuThread") { |
| DCHECK(discardable_shared_memory_manager_); |
| |
| viz::GpuHostImpl::InitFontRenderParams( |
| gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)); |
| |
| bool in_process = !connector || !features::IsMashOopVizEnabled(); |
| |
| viz::mojom::VizMainPtr viz_main_ptr; |
| if (in_process) { |
| // TODO(crbug.com/912221): This goes away after the gpu process split in |
| // mash. |
| gpu_thread_.Start(); |
| gpu_thread_.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&GpuHost::InitializeVizMain, base::Unretained(this), |
| base::Passed(MakeRequest(&viz_main_ptr)))); |
| } else { |
| // Currently, GPU is only run in process in OOP-Ash. |
| NOTREACHED(); |
| } |
| |
| viz::GpuHostImpl::InitParams params; |
| params.restart_id = viz::BeginFrameSource::kNotRestartableId + 1; |
| params.in_process = in_process; |
| params.disable_gpu_shader_disk_cache = |
| base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kDisableGpuShaderDiskCache); |
| params.deadline_to_synchronize_surfaces = |
| switches::GetDeadlineToSynchronizeSurfaces(); |
| params.main_thread_task_runner = main_thread_task_runner_; |
| gpu_host_impl_ = std::make_unique<viz::GpuHostImpl>( |
| this, std::make_unique<viz::VizMainWrapper>(std::move(viz_main_ptr)), |
| std::move(params)); |
| |
| #if defined(OS_WIN) |
| // For OS_WIN the process id for GPU is needed. Using GetCurrentProcessId() |
| // only works with in-process GPU, which is fine because GpuHost isn't used |
| // outside of tests. |
| gpu_host_impl_->OnProcessLaunched(::GetCurrentProcessId()); |
| #endif |
| |
| gpu_memory_buffer_manager_ = |
| std::make_unique<viz::HostGpuMemoryBufferManager>( |
| base::BindRepeating( |
| [](viz::mojom::GpuService* gpu_service, |
| base::OnceClosure connection_error_handler) { |
| return gpu_service; |
| }, |
| gpu_host_impl_->gpu_service()), |
| next_client_id_++, std::make_unique<gpu::GpuMemoryBufferSupport>(), |
| main_thread_task_runner_); |
| |
| shader_cache_factory_ = std::make_unique<gpu::ShaderCacheFactory>(); |
| } |
| |
| GpuHost::~GpuHost() { |
| // TODO(crbug.com/912221): This goes away after the gpu process split in mash. |
| if (gpu_thread_.IsRunning()) { |
| // Stop() will return after |viz_main_impl_| has been destroyed. |
| gpu_thread_.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&GpuHost::DestroyVizMain, base::Unretained(this))); |
| gpu_thread_.Stop(); |
| } |
| |
| viz::GpuHostImpl::ResetFontRenderParams(); |
| } |
| |
| void GpuHost::CreateFrameSinkManager( |
| viz::mojom::FrameSinkManagerRequest request, |
| viz::mojom::FrameSinkManagerClientPtrInfo client) { |
| gpu_host_impl_->ConnectFrameSinkManager(std::move(request), |
| std::move(client)); |
| } |
| |
| void GpuHost::Shutdown() { |
| gpu_host_impl_.reset(); |
| |
| gpu_clients_.clear(); |
| } |
| |
| void GpuHost::Add(mojom::GpuRequest request) { |
| const int client_id = next_client_id_++; |
| const uint64_t client_tracing_id = 0; |
| auto client = std::make_unique<viz::GpuClient>( |
| std::make_unique<GpuClientDelegate>(gpu_host_impl_.get(), |
| gpu_memory_buffer_manager_.get()), |
| client_id, client_tracing_id, main_thread_task_runner_); |
| client->Add(std::move(request)); |
| gpu_clients_.push_back(std::move(client)); |
| } |
| |
| #if defined(OS_CHROMEOS) |
| void GpuHost::AddArc(mojom::ArcRequest request) { |
| arc_bindings_.AddBinding( |
| std::make_unique<ArcClient>(gpu_host_impl_->gpu_service()), |
| std::move(request)); |
| } |
| #endif // defined(OS_CHROMEOS) |
| |
| void GpuHost::OnBadMessageFromGpu() { |
| // TODO(sad): Received some unexpected message from the gpu process. We |
| // should kill the process and restart it. |
| NOTIMPLEMENTED(); |
| } |
| |
| void GpuHost::InitializeVizMain(viz::mojom::VizMainRequest request) { |
| gpu::GpuPreferences gpu_preferences; |
| gpu_preferences.gpu_program_cache_size = |
| gpu::ShaderDiskCache::CacheSizeBytes(); |
| gpu_preferences.texture_target_exception_list = |
| gpu::CreateBufferUsageAndFormatExceptionList(); |
| |
| #if defined(OS_CHROMEOS) && BUILDFLAG(USE_VAAPI) |
| // Initialize media codec. The UI service is running in a privileged process. |
| // We don't need care when to initialize media codec. |
| media::VaapiWrapper::PreSandboxInitialization(); |
| #endif |
| |
| auto gpu_init = std::make_unique<gpu::GpuInit>(); |
| gpu_init->InitializeInProcess(base::CommandLine::ForCurrentProcess(), |
| gpu_preferences); |
| |
| viz::VizMainImpl::ExternalDependencies deps; |
| deps.create_display_compositor = true; |
| viz_main_impl_ = std::make_unique<viz::VizMainImpl>(nullptr, std::move(deps), |
| std::move(gpu_init)); |
| viz_main_impl_->Bind(std::move(request)); |
| } |
| |
| void GpuHost::DestroyVizMain() { |
| DCHECK(viz_main_impl_); |
| viz_main_impl_.reset(); |
| } |
| |
| gpu::GPUInfo GpuHost::GetGPUInfo() const { |
| return gpu_info_; |
| } |
| |
| gpu::GpuFeatureInfo GpuHost::GetGpuFeatureInfo() const { |
| return gpu_feature_info_; |
| } |
| |
| void GpuHost::DidInitialize( |
| const gpu::GPUInfo& gpu_info, |
| const gpu::GpuFeatureInfo& gpu_feature_info, |
| const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu, |
| const base::Optional<gpu::GpuFeatureInfo>& |
| gpu_feature_info_for_hardware_gpu) { |
| gpu_info_ = gpu_info; |
| gpu_feature_info_ = gpu_feature_info; |
| delegate_->OnGpuServiceInitialized(); |
| } |
| |
| void GpuHost::DidFailInitialize() {} |
| |
| void GpuHost::DidCreateContextSuccessfully() {} |
| |
| void GpuHost::BlockDomainFrom3DAPIs(const GURL& url, gpu::DomainGuilt guilt) {} |
| |
| void GpuHost::DisableGpuCompositing() {} |
| |
| bool GpuHost::GpuAccessAllowed() const { |
| return true; |
| } |
| |
| gpu::ShaderCacheFactory* GpuHost::GetShaderCacheFactory() { |
| return shader_cache_factory_.get(); |
| } |
| |
| void GpuHost::RecordLogMessage(int32_t severity, |
| const std::string& header, |
| const std::string& message) {} |
| |
| void GpuHost::BindDiscardableMemoryRequest( |
| discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request) { |
| service_manager::BindSourceInfo source_info; |
| discardable_shared_memory_manager_->Bind(std::move(request), source_info); |
| } |
| |
| void GpuHost::BindInterface(const std::string& interface_name, |
| mojo::ScopedMessagePipeHandle interface_pipe) { |
| NOTREACHED(); |
| } |
| |
| #if defined(USE_OZONE) |
| void GpuHost::TerminateGpuProcess(const std::string& message) {} |
| |
| void GpuHost::SendGpuProcessMessage(IPC::Message* message) {} |
| #endif |
| |
| } // namespace gpu_host |
| } // namespace ws |