blob: 1dfa9975f883570166365aee37c81c911ca1a73e [file] [log] [blame]
Mohsen Izadi0b9fbb62018-08-30 20:30:001// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/viz/host/gpu_host_impl.h"
6
7#include <utility>
8
Sebastien Marchand53801a32019-01-25 16:26:119#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3510#include "base/callback_helpers.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0011#include "base/feature_list.h"
12#include "base/metrics/histogram_macros.h"
13#include "base/no_destructor.h"
14#include "base/threading/thread_checker.h"
Mohsen Izadi63d85e72018-09-06 16:00:2115#include "base/threading/thread_task_runner_handle.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0016#include "base/trace_event/trace_event.h"
Peter McNeeley40245f02021-05-04 21:50:5017#include "base/values.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0018#include "build/build_config.h"
19#include "components/viz/common/features.h"
20#include "gpu/config/gpu_driver_bug_workaround_type.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0021#include "gpu/config/gpu_feature_info.h"
22#include "gpu/config/gpu_finch_features.h"
23#include "gpu/config/gpu_info.h"
24#include "gpu/ipc/common/gpu_client_ids.h"
25#include "gpu/ipc/host/shader_disk_cache.h"
John Abd-El-Malekb36a3792021-04-19 20:54:3126#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
Mohsen Izadi63d85e72018-09-06 16:00:2127#include "ui/base/ui_base_features.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0028#include "ui/gfx/font_render_params.h"
29
30#if defined(OS_ANDROID)
31#include "base/android/build_info.h"
32#endif
33
34#if defined(OS_WIN)
35#include "ui/gfx/win/rendering_window_manager.h"
36#endif
37
Maksim Sisov4f5918f2020-06-24 08:26:0038#if defined(USE_OZONE)
Peng Huang2d5cf682020-07-31 14:07:4739#include "ui/ozone/public/gpu_platform_support_host.h"
40#include "ui/ozone/public/ozone_platform.h"
Maksim Sisov4f5918f2020-06-24 08:26:0041#endif
42
Mohsen Izadi0b9fbb62018-08-30 20:30:0043namespace viz {
44namespace {
45
46// A wrapper around gfx::FontRenderParams that checks it is set and accessed on
47// the same thread.
48class FontRenderParams {
49 public:
50 void Set(const gfx::FontRenderParams& params);
Mohsen Izadif9505d82018-10-06 01:34:0351 void Reset();
Anton Bikineev1156b5f2021-05-15 22:35:3652 const absl::optional<gfx::FontRenderParams>& Get();
Mohsen Izadi0b9fbb62018-08-30 20:30:0053
54 private:
55 friend class base::NoDestructor<FontRenderParams>;
56
57 FontRenderParams();
58 ~FontRenderParams();
59
60 THREAD_CHECKER(thread_checker_);
Anton Bikineev1156b5f2021-05-15 22:35:3661 absl::optional<gfx::FontRenderParams> params_;
Mohsen Izadi0b9fbb62018-08-30 20:30:0062
63 DISALLOW_COPY_AND_ASSIGN(FontRenderParams);
64};
65
66void FontRenderParams::Set(const gfx::FontRenderParams& params) {
67 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
68 params_ = params;
69}
70
Mohsen Izadif9505d82018-10-06 01:34:0371void FontRenderParams::Reset() {
72 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Anton Bikineev1156b5f2021-05-15 22:35:3673 params_ = absl::nullopt;
Mohsen Izadif9505d82018-10-06 01:34:0374}
75
Anton Bikineev1156b5f2021-05-15 22:35:3676const absl::optional<gfx::FontRenderParams>& FontRenderParams::Get() {
Mohsen Izadi0b9fbb62018-08-30 20:30:0077 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
78 return params_;
79}
80
81FontRenderParams::FontRenderParams() = default;
82
83FontRenderParams::~FontRenderParams() {
84 NOTREACHED();
85}
86
87FontRenderParams& GetFontRenderParams() {
88 static base::NoDestructor<FontRenderParams> instance;
89 return *instance;
90}
91
92} // namespace
93
94GpuHostImpl::InitParams::InitParams() = default;
95
96GpuHostImpl::InitParams::InitParams(InitParams&&) = default;
97
98GpuHostImpl::InitParams::~InitParams() = default;
99
100GpuHostImpl::GpuHostImpl(Delegate* delegate,
Ken Rockot7f8a2822021-04-06 23:27:52101 mojo::PendingRemote<mojom::VizMain> viz_main,
Mohsen Izadi0b9fbb62018-08-30 20:30:00102 InitParams params)
103 : delegate_(delegate),
kylechar80dd2aa2019-07-22 15:31:39104 viz_main_(std::move(viz_main)),
Mohsen Izadi0b9fbb62018-08-30 20:30:00105 params_(std::move(params)),
Shimi Zhang88ae9222019-07-19 16:54:16106 host_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
Maggie Chena6ece772020-04-27 17:19:06107 // Create a special GPU info collection service if the GPU process is used for
108 // info collection only.
109#if defined(OS_WIN)
110 if (params.info_collection_gpu_process) {
111 viz_main_->CreateInfoCollectionGpuService(
112 info_collection_gpu_service_remote_.BindNewPipeAndPassReceiver());
113 return;
114 }
115#endif
116
Mohsen Izadi0b9fbb62018-08-30 20:30:00117 DCHECK(delegate_);
Mohsen Izadi0b9fbb62018-08-30 20:30:00118
Julie Jeongeun Kim7b4a6aa12019-09-20 14:57:12119 mojo::PendingRemote<discardable_memory::mojom::DiscardableSharedMemoryManager>
120 discardable_manager_remote;
121 delegate_->BindDiscardableMemoryReceiver(
122 discardable_manager_remote.InitWithNewPipeAndPassReceiver());
Mohsen Izadi0b9fbb62018-08-30 20:30:00123
124 DCHECK(GetFontRenderParams().Get());
kylechar80dd2aa2019-07-22 15:31:39125 viz_main_->CreateGpuService(gpu_service_remote_.BindNewPipeAndPassReceiver(),
126 gpu_host_receiver_.BindNewPipeAndPassRemote(),
Julie Jeongeun Kim7b4a6aa12019-09-20 14:57:12127 std::move(discardable_manager_remote),
kylechar80dd2aa2019-07-22 15:31:39128 activity_flags_.CloneHandle(),
129 GetFontRenderParams().Get()->subpixel_rendering);
Mohsen Izadi63d85e72018-09-06 16:00:21130
131#if defined(USE_OZONE)
Maksim Sisov4f5918f2020-06-24 08:26:00132 if (features::IsUsingOzonePlatform())
133 InitOzone();
Mohsen Izadi63d85e72018-09-06 16:00:21134#endif // defined(USE_OZONE)
Mohsen Izadi0b9fbb62018-08-30 20:30:00135}
136
Mohsen Izadif9505d82018-10-06 01:34:03137GpuHostImpl::~GpuHostImpl() {
138 SendOutstandingReplies();
139}
Mohsen Izadi0b9fbb62018-08-30 20:30:00140
141// static
142void GpuHostImpl::InitFontRenderParams(const gfx::FontRenderParams& params) {
143 DCHECK(!GetFontRenderParams().Get());
144 GetFontRenderParams().Set(params);
145}
146
Mohsen Izadif9505d82018-10-06 01:34:03147// static
148void GpuHostImpl::ResetFontRenderParams() {
149 DCHECK(GetFontRenderParams().Get());
150 GetFontRenderParams().Reset();
151}
152
kylechar9b37f172019-09-19 22:55:27153void GpuHostImpl::SetProcessId(base::ProcessId pid) {
Mohsen Izadi0b9fbb62018-08-30 20:30:00154 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
155 DCHECK_EQ(base::kNullProcessId, pid_);
156 DCHECK_NE(base::kNullProcessId, pid);
157 pid_ = pid;
158}
159
160void GpuHostImpl::OnProcessCrashed() {
161 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
162
163 // If the GPU process crashed while compiling a shader, we may have invalid
164 // cached binaries. Completely clear the shader cache to force shader binaries
165 // to be re-created.
166 if (activity_flags_.IsFlagSet(
167 gpu::ActivityFlagsBase::FLAG_LOADING_PROGRAM_BINARY)) {
168 auto* shader_cache_factory = delegate_->GetShaderCacheFactory();
169 for (auto cache_key : client_id_to_shader_cache_) {
170 // This call will temporarily extend the lifetime of the cache (kept
171 // alive in the factory), and may drop loads of cached shader binaries if
172 // it takes a while to complete. As we are intentionally dropping all
173 // binaries, this behavior is fine.
174 shader_cache_factory->ClearByClientId(
175 cache_key.first, base::Time(), base::Time::Max(), base::DoNothing());
176 }
177 }
178}
179
Mohsen Izadibabed2b2018-08-31 01:37:39180void GpuHostImpl::AddConnectionErrorHandler(base::OnceClosure handler) {
181 connection_error_handlers_.push_back(std::move(handler));
182}
183
Mohsen Izadi0b9fbb62018-08-30 20:30:00184void GpuHostImpl::BlockLiveOffscreenContexts() {
185 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
186
187 for (auto iter = urls_with_live_offscreen_contexts_.begin();
188 iter != urls_with_live_offscreen_contexts_.end(); ++iter) {
Mohsen Izadi312c6922018-09-07 14:21:36189 delegate_->BlockDomainFrom3DAPIs(*iter, gpu::DomainGuilt::kUnknown);
Mohsen Izadi0b9fbb62018-08-30 20:30:00190 }
191}
192
193void GpuHostImpl::ConnectFrameSinkManager(
Mario Sanchez Prada745dd5e2019-10-16 14:14:30194 mojo::PendingReceiver<mojom::FrameSinkManager> receiver,
Alexander Alekseev81b01612020-07-10 22:56:29195 mojo::PendingRemote<mojom::FrameSinkManagerClient> client,
196 const DebugRendererSettings& debug_renderer_settings) {
Mohsen Izadi0b9fbb62018-08-30 20:30:00197 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
198 TRACE_EVENT0("gpu", "GpuHostImpl::ConnectFrameSinkManager");
199
200 mojom::FrameSinkManagerParamsPtr params =
201 mojom::FrameSinkManagerParams::New();
202 params->restart_id = params_.restart_id;
203 params->use_activation_deadline =
204 params_.deadline_to_synchronize_surfaces.has_value();
205 params->activation_deadline_in_frames =
206 params_.deadline_to_synchronize_surfaces.value_or(0u);
Mario Sanchez Prada745dd5e2019-10-16 14:14:30207 params->frame_sink_manager = std::move(receiver);
Mohsen Izadi0b9fbb62018-08-30 20:30:00208 params->frame_sink_manager_client = std::move(client);
Alexander Alekseev81b01612020-07-10 22:56:29209 params->debug_renderer_settings = debug_renderer_settings;
kylechar80dd2aa2019-07-22 15:31:39210 viz_main_->CreateFrameSinkManager(std::move(params));
Mohsen Izadi0b9fbb62018-08-30 20:30:00211}
212
Robert Seseka9b47c92019-08-30 01:22:54213#if BUILDFLAG(USE_VIZ_DEVTOOLS)
Sean Gilhulyda1ee4b2018-11-13 21:56:09214void GpuHostImpl::ConnectVizDevTools(mojom::VizDevToolsParamsPtr params) {
kylechar80dd2aa2019-07-22 15:31:39215 viz_main_->CreateVizDevTools(std::move(params));
Sean Gilhulyda1ee4b2018-11-13 21:56:09216}
217#endif
218
Mohsen Izadi0b9fbb62018-08-30 20:30:00219void GpuHostImpl::EstablishGpuChannel(int client_id,
220 uint64_t client_tracing_id,
221 bool is_gpu_host,
John Abd-El-Malekb36a3792021-04-19 20:54:31222 bool sync,
Mohsen Izadi0b9fbb62018-08-30 20:30:00223 EstablishChannelCallback callback) {
224 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
225 TRACE_EVENT0("gpu", "GpuHostImpl::EstablishGpuChannel");
226
Bo Liu95570f32020-03-16 23:42:17227 shutdown_timeout_.Stop();
228
Sean Gilhulyd2ef4022020-08-20 18:18:56229 // If GPU features are already blocklisted, no need to establish the channel.
Mohsen Izadi0b9fbb62018-08-30 20:30:00230 if (!delegate_->GpuAccessAllowed()) {
Sean Gilhulyd2ef4022020-08-20 18:18:56231 DVLOG(1) << "GPU access blocked, refusing to open a GPU channel.";
Mohsen Izadi0b9fbb62018-08-30 20:30:00232 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
233 gpu::GpuFeatureInfo(),
234 EstablishChannelStatus::kGpuAccessDenied);
235 return;
236 }
237
238 if (gpu::IsReservedClientId(client_id)) {
239 // The display-compositor/GrShaderCache in the gpu process uses these
240 // special client ids.
241 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
242 gpu::GpuFeatureInfo(),
243 EstablishChannelStatus::kGpuAccessDenied);
244 return;
245 }
246
247 bool cache_shaders_on_disk =
248 delegate_->GetShaderCacheFactory()->Get(client_id) != nullptr;
249
John Abd-El-Malekb36a3792021-04-19 20:54:31250 channel_requests_[client_id] = std::move(callback);
251 if (sync) {
252 mojo::ScopedMessagePipeHandle channel_handle;
253 gpu::GPUInfo gpu_info;
254 gpu::GpuFeatureInfo gpu_feature_info;
255 {
256 mojo::SyncCallRestrictions::ScopedAllowSyncCall scoped_allow;
257 gpu_service_remote_->EstablishGpuChannel(
258 client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk,
259 &channel_handle, &gpu_info, &gpu_feature_info);
260 }
261 OnChannelEstablished(client_id, true, std::move(channel_handle), gpu_info,
262 gpu_feature_info);
263 } else {
264 gpu_service_remote_->EstablishGpuChannel(
265 client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk,
266 base::BindOnce(&GpuHostImpl::OnChannelEstablished,
267 weak_ptr_factory_.GetWeakPtr(), client_id, false));
268 }
Mohsen Izadi0b9fbb62018-08-30 20:30:00269
Jonathan Backer06c419e12019-01-22 14:37:14270 if (!params_.disable_gpu_shader_disk_cache)
Mohsen Izadi0b9fbb62018-08-30 20:30:00271 CreateChannelCache(client_id);
Mohsen Izadi0b9fbb62018-08-30 20:30:00272}
273
John Abd-El-Malekb36a3792021-04-19 20:54:31274void GpuHostImpl::CloseChannel(int client_id) {
275 gpu_service_remote_->CloseChannel(client_id);
276
277 channel_requests_.erase(client_id);
278}
Peter McNeeley40245f02021-05-04 21:50:50279#if BUILDFLAG(USE_VIZ_DEBUGGER)
280void GpuHostImpl::FilterVisualDebugStream(base::Value json) {
281 viz_main_->FilterDebugStream(std::move(json));
282}
283
284void GpuHostImpl::StartVisualDebugStream(
285 base::RepeatingCallback<void(base::Value)> callback) {
286 viz_debug_output_callback_ = std::move(callback);
287 viz_main_->StartDebugStream(viz_debug_output_.BindNewPipeAndPassRemote());
288}
289
290void GpuHostImpl::StopVisualDebugStream() {
291 viz_main_->StopDebugStream();
292 viz_debug_output_.reset();
293}
294#endif
John Abd-El-Malekb36a3792021-04-19 20:54:31295
Mohsen Izadi0b9fbb62018-08-30 20:30:00296void GpuHostImpl::SendOutstandingReplies() {
297 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
298
Mohsen Izadibabed2b2018-08-31 01:37:39299 for (auto& handler : connection_error_handlers_)
300 std::move(handler).Run();
301 connection_error_handlers_.clear();
302
Mohsen Izadi0b9fbb62018-08-30 20:30:00303 // Send empty channel handles for all EstablishChannel requests.
John Abd-El-Malekb36a3792021-04-19 20:54:31304 for (auto& entry : channel_requests_) {
305 std::move(entry.second)
306 .Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
307 gpu::GpuFeatureInfo(), EstablishChannelStatus::kGpuHostInvalid);
Mohsen Izadi0b9fbb62018-08-30 20:30:00308 }
John Abd-El-Malekb36a3792021-04-19 20:54:31309 channel_requests_.clear();
Mohsen Izadi0b9fbb62018-08-30 20:30:00310}
311
Mohsen Izadi63d85e72018-09-06 16:00:21312void GpuHostImpl::BindInterface(const std::string& interface_name,
313 mojo::ScopedMessagePipeHandle interface_pipe) {
314 delegate_->BindInterface(interface_name, std::move(interface_pipe));
315}
316
Mohsen Izadi0b9fbb62018-08-30 20:30:00317mojom::GpuService* GpuHostImpl::gpu_service() {
318 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Shimi Zhang88ae9222019-07-19 16:54:16319 DCHECK(gpu_service_remote_.is_bound());
320 return gpu_service_remote_.get();
Mohsen Izadi0b9fbb62018-08-30 20:30:00321}
322
Maggie Chena6ece772020-04-27 17:19:06323#if defined(OS_WIN)
324mojom::InfoCollectionGpuService* GpuHostImpl::info_collection_gpu_service() {
325 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
326 DCHECK(info_collection_gpu_service_remote_.is_bound());
327 return info_collection_gpu_service_remote_.get();
328}
329#endif
330
Mohsen Izadi63d85e72018-09-06 16:00:21331#if defined(USE_OZONE)
Mohsen Izadia378a8f42019-08-02 02:34:19332
Mohsen Izadi63d85e72018-09-06 16:00:21333void GpuHostImpl::InitOzone() {
Maksim Sisov4f5918f2020-06-24 08:26:00334 DCHECK(features::IsUsingOzonePlatform());
Mohsen Izadi63d85e72018-09-06 16:00:21335 // Ozone needs to send the primary DRM device to GPU service as early as
336 // possible to ensure the latter always has a valid device.
337 // https://crbug.com/608839
Maksim Sisov2e064342018-10-03 10:35:06338 //
339 // The Ozone/Wayland requires mojo communication to be established to be
340 // functional with a separate gpu process. Thus, using the PlatformProperties,
341 // check if there is such a requirement.
Kramer Gec78fde4e2020-04-18 18:58:06342 auto interface_binder = base::BindRepeating(&GpuHostImpl::BindInterface,
343 weak_ptr_factory_.GetWeakPtr());
344 auto terminate_callback = base::BindOnce(&GpuHostImpl::TerminateGpuProcess,
345 weak_ptr_factory_.GetWeakPtr());
Mohsen Izadi63d85e72018-09-06 16:00:21346
Kramer Gec78fde4e2020-04-18 18:58:06347 ui::OzonePlatform::GetInstance()
348 ->GetGpuPlatformSupportHost()
349 ->OnGpuServiceLaunched(params_.restart_id,
350 params_.main_thread_task_runner,
351 host_thread_task_runner_, interface_binder,
352 std::move(terminate_callback));
Mohsen Izadi63d85e72018-09-06 16:00:21353}
354
355void GpuHostImpl::TerminateGpuProcess(const std::string& message) {
356 delegate_->TerminateGpuProcess(message);
357}
358
359#endif // defined(USE_OZONE)
360
Mohsen Izadi0b9fbb62018-08-30 20:30:00361std::string GpuHostImpl::GetShaderPrefixKey() {
362 if (shader_prefix_key_.empty()) {
363 const gpu::GPUInfo& info = delegate_->GetGPUInfo();
364 const gpu::GPUInfo::GPUDevice& active_gpu = info.active_gpu();
365
366 shader_prefix_key_ = params_.product + "-" + info.gl_vendor + "-" +
367 info.gl_renderer + "-" + active_gpu.driver_version +
368 "-" + active_gpu.driver_vendor;
369
370#if defined(OS_ANDROID)
371 std::string build_fp =
372 base::android::BuildInfo::GetInstance()->android_build_fp();
Mohsen Izadi0b9fbb62018-08-30 20:30:00373 shader_prefix_key_ += "-" + build_fp;
374#endif
375 }
376
377 return shader_prefix_key_;
378}
379
380void GpuHostImpl::LoadedShader(int32_t client_id,
381 const std::string& key,
382 const std::string& data) {
383 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
384
385 std::string prefix = GetShaderPrefixKey();
386 bool prefix_ok = !key.compare(0, prefix.length(), prefix);
387 UMA_HISTOGRAM_BOOLEAN("GPU.ShaderLoadPrefixOK", prefix_ok);
388 if (prefix_ok) {
389 // Remove the prefix from the key before load.
390 std::string key_no_prefix = key.substr(prefix.length() + 1);
Shimi Zhang88ae9222019-07-19 16:54:16391 gpu_service_remote_->LoadedShader(client_id, key_no_prefix, data);
Mohsen Izadi0b9fbb62018-08-30 20:30:00392 }
393}
394
395void GpuHostImpl::CreateChannelCache(int32_t client_id) {
396 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
397 TRACE_EVENT0("gpu", "GpuHostImpl::CreateChannelCache");
398
399 scoped_refptr<gpu::ShaderDiskCache> cache =
400 delegate_->GetShaderCacheFactory()->Get(client_id);
401 if (!cache)
402 return;
403
404 cache->set_shader_loaded_callback(base::BindRepeating(
405 &GpuHostImpl::LoadedShader, weak_ptr_factory_.GetWeakPtr(), client_id));
406
407 client_id_to_shader_cache_[client_id] = cache;
408}
409
410void GpuHostImpl::OnChannelEstablished(
411 int client_id,
John Abd-El-Malekb36a3792021-04-19 20:54:31412 bool sync,
413 mojo::ScopedMessagePipeHandle channel_handle,
414 const gpu::GPUInfo& gpu_info,
415 const gpu::GpuFeatureInfo& gpu_feature_info) {
Mohsen Izadi0b9fbb62018-08-30 20:30:00416 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
417 TRACE_EVENT0("gpu", "GpuHostImpl::OnChannelEstablished");
418
John Abd-El-Malekb36a3792021-04-19 20:54:31419 auto it = channel_requests_.find(client_id);
420 if (it == channel_requests_.end())
421 return;
422
423 auto callback = std::move(it->second);
424 channel_requests_.erase(it);
Mohsen Izadi0b9fbb62018-08-30 20:30:00425
Sean Gilhulyd2ef4022020-08-20 18:18:56426 // Currently if any of the GPU features are blocklisted, we don't establish a
Mohsen Izadi0b9fbb62018-08-30 20:30:00427 // GPU channel.
428 if (channel_handle.is_valid() && !delegate_->GpuAccessAllowed()) {
Shimi Zhang88ae9222019-07-19 16:54:16429 gpu_service_remote_->CloseChannel(client_id);
Mohsen Izadi0b9fbb62018-08-30 20:30:00430 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
431 gpu::GpuFeatureInfo(),
432 EstablishChannelStatus::kGpuAccessDenied);
433 RecordLogMessage(logging::LOG_WARNING, "WARNING",
434 "Hardware acceleration is unavailable.");
435 return;
436 }
437
John Abd-El-Malekb36a3792021-04-19 20:54:31438 // TODO(jam): always use GPUInfo & GpuFeatureInfo from the service once we
439 // know there's no issue with the ProcessHostOnUI which is the only mode
440 // that currently uses it. This is because in that mode the sync mojo call
441 // in the caller means we won't get the async DidInitialize() call before
442 // this point, so the delegate_ methods won't have the GPU info structs yet.
443 if (sync) {
444 std::move(callback).Run(std::move(channel_handle), gpu_info,
445 gpu_feature_info, EstablishChannelStatus::kSuccess);
446 } else {
447 std::move(callback).Run(std::move(channel_handle), delegate_->GetGPUInfo(),
448 delegate_->GetGpuFeatureInfo(),
449 EstablishChannelStatus::kSuccess);
450 }
Mohsen Izadi0b9fbb62018-08-30 20:30:00451}
452
453void GpuHostImpl::DidInitialize(
454 const gpu::GPUInfo& gpu_info,
455 const gpu::GpuFeatureInfo& gpu_feature_info,
Anton Bikineev1156b5f2021-05-15 22:35:36456 const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
457 const absl::optional<gpu::GpuFeatureInfo>&
Jonah Ryan-Davisa70577c2019-06-26 18:54:31458 gpu_feature_info_for_hardware_gpu,
Alexander Dunaeve6e09c12020-10-23 16:43:42459 const gfx::GpuExtraInfo& gpu_extra_info) {
Mohsen Izadi0b9fbb62018-08-30 20:30:00460 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", true);
Mohsen Izadi0b9fbb62018-08-30 20:30:00461
462 // Set GPU driver bug workaround flags that are checked on the browser side.
463 wake_up_gpu_before_drawing_ =
464 gpu_feature_info.IsWorkaroundEnabled(gpu::WAKE_UP_GPU_BEFORE_DRAWING);
Mohsen Izadi0b9fbb62018-08-30 20:30:00465
Mohsen Izadif9505d82018-10-06 01:34:03466 delegate_->DidInitialize(gpu_info, gpu_feature_info,
Mohsen Izadi0b9fbb62018-08-30 20:30:00467 gpu_info_for_hardware_gpu,
Jonah Ryan-Davisa70577c2019-06-26 18:54:31468 gpu_feature_info_for_hardware_gpu, gpu_extra_info);
Jonathan Backer06c419e12019-01-22 14:37:14469
470 if (!params_.disable_gpu_shader_disk_cache) {
kylechar90f620c2020-08-18 17:08:41471 CreateChannelCache(gpu::kDisplayCompositorClientId);
Jonathan Backer06c419e12019-01-22 14:37:14472
Peng Huang70021682019-09-18 19:42:28473 bool use_gr_shader_cache = base::FeatureList::IsEnabled(
474 features::kDefaultEnableOopRasterization) ||
475 features::IsUsingSkiaRenderer();
Jonathan Backer06c419e12019-01-22 14:37:14476 if (use_gr_shader_cache)
477 CreateChannelCache(gpu::kGrShaderCacheClientId);
478 }
Mohsen Izadi0b9fbb62018-08-30 20:30:00479}
480
481void GpuHostImpl::DidFailInitialize() {
482 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", false);
483 delegate_->DidFailInitialize();
484}
485
486void GpuHostImpl::DidCreateContextSuccessfully() {
487 delegate_->DidCreateContextSuccessfully();
488}
489
490void GpuHostImpl::DidCreateOffscreenContext(const GURL& url) {
491 urls_with_live_offscreen_contexts_.insert(url);
492}
493
494void GpuHostImpl::DidDestroyOffscreenContext(const GURL& url) {
495 // We only want to remove *one* of the entries in the multiset for this
496 // particular URL, so can't use the erase method taking a key.
497 auto candidate = urls_with_live_offscreen_contexts_.find(url);
498 if (candidate != urls_with_live_offscreen_contexts_.end())
499 urls_with_live_offscreen_contexts_.erase(candidate);
500}
501
502void GpuHostImpl::DidDestroyChannel(int32_t client_id) {
503 TRACE_EVENT0("gpu", "GpuHostImpl::DidDestroyChannel");
504 client_id_to_shader_cache_.erase(client_id);
505}
506
Bo Liu95570f32020-03-16 23:42:17507void GpuHostImpl::DidDestroyAllChannels() {
508 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
509 if (!channel_requests_.empty())
510 return;
511 constexpr base::TimeDelta kShutDownTimeout = base::TimeDelta::FromSeconds(10);
512 shutdown_timeout_.Start(FROM_HERE, kShutDownTimeout,
513 base::BindOnce(&GpuHostImpl::MaybeShutdownGpuProcess,
514 base::Unretained(this)));
515}
516
517void GpuHostImpl::MaybeShutdownGpuProcess() {
518 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
519 DCHECK(channel_requests_.empty());
520 delegate_->MaybeShutdownGpuProcess();
521}
522
Mohsen Izadi0b9fbb62018-08-30 20:30:00523void GpuHostImpl::DidLoseContext(bool offscreen,
524 gpu::error::ContextLostReason reason,
525 const GURL& active_url) {
526 // TODO(kbr): would be nice to see the "offscreen" flag too.
527 TRACE_EVENT2("gpu", "GpuHostImpl::DidLoseContext", "reason", reason, "url",
528 active_url.possibly_invalid_spec());
529
Patrick Todf5911c2020-05-12 19:31:42530 if (active_url.is_empty()) {
Mohsen Izadi0b9fbb62018-08-30 20:30:00531 return;
532 }
533
Mohsen Izadi312c6922018-09-07 14:21:36534 gpu::DomainGuilt guilt = gpu::DomainGuilt::kUnknown;
Mohsen Izadi0b9fbb62018-08-30 20:30:00535 switch (reason) {
536 case gpu::error::kGuilty:
Mohsen Izadi312c6922018-09-07 14:21:36537 guilt = gpu::DomainGuilt::kKnown;
Mohsen Izadi0b9fbb62018-08-30 20:30:00538 break;
539 // Treat most other error codes as though they had unknown provenance.
540 // In practice this doesn't affect the user experience. A lost context
541 // of either known or unknown guilt still causes user-level 3D APIs
542 // (e.g. WebGL) to be blocked on that domain until the user manually
543 // reenables them.
544 case gpu::error::kUnknown:
545 case gpu::error::kOutOfMemory:
546 case gpu::error::kMakeCurrentFailed:
547 case gpu::error::kGpuChannelLost:
548 case gpu::error::kInvalidGpuMessage:
549 break;
550 case gpu::error::kInnocent:
551 return;
552 }
553
554 delegate_->BlockDomainFrom3DAPIs(active_url, guilt);
555}
556
557void GpuHostImpl::DisableGpuCompositing() {
558 delegate_->DisableGpuCompositing();
559}
560
Jonah Ryan-Davisa54a3002020-12-08 17:34:50561void GpuHostImpl::DidUpdateGPUInfo(const gpu::GPUInfo& gpu_info) {
562 delegate_->DidUpdateGPUInfo(gpu_info);
563}
564
Mohsen Izadi50c28052018-09-07 00:32:14565#if defined(OS_WIN)
Maggie Chen8f177172020-02-11 00:02:28566void GpuHostImpl::DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) {
567 delegate_->DidUpdateOverlayInfo(overlay_info);
568}
569
Maggie Chen05364bf32020-06-03 08:34:06570void GpuHostImpl::DidUpdateHDRStatus(bool hdr_enabled) {
571 delegate_->DidUpdateHDRStatus(hdr_enabled);
572}
573
Mohsen Izadi0b9fbb62018-08-30 20:30:00574void GpuHostImpl::SetChildSurface(gpu::SurfaceHandle parent,
575 gpu::SurfaceHandle child) {
kylechar89341da82018-09-10 15:26:27576 if (pid_ != base::kNullProcessId) {
577 gfx::RenderingWindowManager::GetInstance()->RegisterChild(
578 parent, child, /*expected_child_process_id=*/pid_);
Mohsen Izadi0b9fbb62018-08-30 20:30:00579 }
Mohsen Izadi0b9fbb62018-08-30 20:30:00580}
Mohsen Izadi50c28052018-09-07 00:32:14581#endif // defined(OS_WIN)
Mohsen Izadi0b9fbb62018-08-30 20:30:00582
583void GpuHostImpl::StoreShaderToDisk(int32_t client_id,
584 const std::string& key,
585 const std::string& shader) {
586 TRACE_EVENT0("gpu", "GpuHostImpl::StoreShaderToDisk");
587 auto iter = client_id_to_shader_cache_.find(client_id);
588 // If the cache doesn't exist then this is an off the record profile.
589 if (iter == client_id_to_shader_cache_.end())
590 return;
591 std::string prefix = GetShaderPrefixKey();
592 iter->second->Cache(prefix + ":" + key, shader);
593}
594
595void GpuHostImpl::RecordLogMessage(int32_t severity,
596 const std::string& header,
597 const std::string& message) {
598 delegate_->RecordLogMessage(severity, header, message);
599}
600
Peter McNeeley40245f02021-05-04 21:50:50601#if BUILDFLAG(USE_VIZ_DEBUGGER)
602void GpuHostImpl::LogFrame(base::Value frame_data) {
603 if (!viz_debug_output_callback_.is_null())
604 viz_debug_output_callback_.Run(std::move(frame_data));
605}
606#endif
607
Mohsen Izadi0b9fbb62018-08-30 20:30:00608} // namespace viz