blob: c3ca3c950f6c0af4487cc20fbbcfe3d5b1704d6f [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
9#include "base/bind_helpers.h"
10#include "base/command_line.h"
11#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"
17#include "build/build_config.h"
18#include "components/viz/common/features.h"
19#include "gpu/config/gpu_driver_bug_workaround_type.h"
20#include "gpu/config/gpu_feature_info.h"
21#include "gpu/config/gpu_finch_features.h"
22#include "gpu/config/gpu_info.h"
23#include "gpu/ipc/common/gpu_client_ids.h"
24#include "gpu/ipc/host/shader_disk_cache.h"
Mohsen Izadi63d85e72018-09-06 16:00:2125#include "ui/base/ui_base_features.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0026#include "ui/gfx/font_render_params.h"
Mohsen Izadi63d85e72018-09-06 16:00:2127#include "ui/ozone/public/gpu_platform_support_host.h"
28#include "ui/ozone/public/ozone_platform.h"
Mohsen Izadi0b9fbb62018-08-30 20:30:0029
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
38namespace viz {
39namespace {
40
41// A wrapper around gfx::FontRenderParams that checks it is set and accessed on
42// the same thread.
43class FontRenderParams {
44 public:
45 void Set(const gfx::FontRenderParams& params);
Mohsen Izadif9505d82018-10-06 01:34:0346 void Reset();
Mohsen Izadi0b9fbb62018-08-30 20:30:0047 const base::Optional<gfx::FontRenderParams>& Get();
48
49 private:
50 friend class base::NoDestructor<FontRenderParams>;
51
52 FontRenderParams();
53 ~FontRenderParams();
54
55 THREAD_CHECKER(thread_checker_);
56 base::Optional<gfx::FontRenderParams> params_;
57
58 DISALLOW_COPY_AND_ASSIGN(FontRenderParams);
59};
60
61void FontRenderParams::Set(const gfx::FontRenderParams& params) {
62 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
63 params_ = params;
64}
65
Mohsen Izadif9505d82018-10-06 01:34:0366void FontRenderParams::Reset() {
67 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
68 params_ = base::nullopt;
69}
70
Mohsen Izadi0b9fbb62018-08-30 20:30:0071const base::Optional<gfx::FontRenderParams>& FontRenderParams::Get() {
72 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
73 return params_;
74}
75
76FontRenderParams::FontRenderParams() = default;
77
78FontRenderParams::~FontRenderParams() {
79 NOTREACHED();
80}
81
82FontRenderParams& GetFontRenderParams() {
83 static base::NoDestructor<FontRenderParams> instance;
84 return *instance;
85}
86
Mohsen Izadi63d85e72018-09-06 16:00:2187#if defined(USE_OZONE)
88// Helper to register Mus/conventional thread bouncers for ozone startup.
89void OzoneRegisterStartupCallbackHelper(
90 scoped_refptr<base::SingleThreadTaskRunner> host_thread_task_runner,
91 base::OnceCallback<void(ui::OzonePlatform*)> callback) {
92 // The callback registered in ozone can be called in any thread. So use an
93 // intermediary callback that bounces to the GpuHost thread if needed, before
94 // running the callback.
95 auto bounce_callback = base::BindOnce(
96 [](base::SingleThreadTaskRunner* host_thread_task_runner,
97 base::OnceCallback<void(ui::OzonePlatform*)> callback,
98 ui::OzonePlatform* platform) {
99 if (host_thread_task_runner->BelongsToCurrentThread()) {
100 std::move(callback).Run(platform);
101 } else {
102 host_thread_task_runner->PostTask(
103 FROM_HERE, base::BindOnce(std::move(callback), platform));
104 }
105 },
106 base::RetainedRef(host_thread_task_runner), std::move(callback));
107 ui::OzonePlatform::RegisterStartupCallback(std::move(bounce_callback));
108}
109#endif // defined(USE_OZONE)
110
Mohsen Izadi0b9fbb62018-08-30 20:30:00111} // namespace
112
Mohsen Izadif9505d82018-10-06 01:34:03113VizMainWrapper::VizMainWrapper(mojom::VizMainPtr viz_main_ptr)
114 : viz_main_ptr_(std::move(viz_main_ptr)) {}
115
116VizMainWrapper::VizMainWrapper(
117 mojom::VizMainAssociatedPtr viz_main_associated_ptr)
118 : viz_main_associated_ptr_(std::move(viz_main_associated_ptr)) {}
119
120VizMainWrapper::~VizMainWrapper() = default;
121
122void VizMainWrapper::CreateGpuService(
123 mojom::GpuServiceRequest request,
124 mojom::GpuHostPtr gpu_host,
125 discardable_memory::mojom::DiscardableSharedMemoryManagerPtr
126 discardable_memory_manager,
127 mojo::ScopedSharedBufferHandle activity_flags,
128 gfx::FontRenderParams::SubpixelRendering subpixel_rendering) {
129 if (viz_main_ptr_) {
130 viz_main_ptr_->CreateGpuService(std::move(request), std::move(gpu_host),
131 std::move(discardable_memory_manager),
132 std::move(activity_flags),
133 subpixel_rendering);
134 } else {
135 viz_main_associated_ptr_->CreateGpuService(
136 std::move(request), std::move(gpu_host),
137 std::move(discardable_memory_manager), std::move(activity_flags),
138 subpixel_rendering);
139 }
140}
141
142void VizMainWrapper::CreateFrameSinkManager(
143 mojom::FrameSinkManagerParamsPtr params) {
144 if (viz_main_ptr_)
145 viz_main_ptr_->CreateFrameSinkManager(std::move(params));
146 else
147 viz_main_associated_ptr_->CreateFrameSinkManager(std::move(params));
148}
149
Mohsen Izadi0b9fbb62018-08-30 20:30:00150GpuHostImpl::InitParams::InitParams() = default;
151
152GpuHostImpl::InitParams::InitParams(InitParams&&) = default;
153
154GpuHostImpl::InitParams::~InitParams() = default;
155
156GpuHostImpl::GpuHostImpl(Delegate* delegate,
Mohsen Izadif9505d82018-10-06 01:34:03157 std::unique_ptr<VizMainWrapper> viz_main_ptr,
Mohsen Izadi0b9fbb62018-08-30 20:30:00158 InitParams params)
159 : delegate_(delegate),
Mohsen Izadif9505d82018-10-06 01:34:03160 viz_main_ptr_(std::move(viz_main_ptr)),
Mohsen Izadi0b9fbb62018-08-30 20:30:00161 params_(std::move(params)),
Mohsen Izadi63d85e72018-09-06 16:00:21162 host_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
Mohsen Izadi0b9fbb62018-08-30 20:30:00163 gpu_host_binding_(this),
164 weak_ptr_factory_(this) {
165 DCHECK(delegate_);
Mohsen Izadi0b9fbb62018-08-30 20:30:00166 mojom::GpuHostPtr host_proxy;
167 gpu_host_binding_.Bind(mojo::MakeRequest(&host_proxy));
168
169 discardable_memory::mojom::DiscardableSharedMemoryManagerPtr
170 discardable_manager_ptr;
171 auto discardable_request = mojo::MakeRequest(&discardable_manager_ptr);
172 delegate_->BindDiscardableMemoryRequest(std::move(discardable_request));
173
174 DCHECK(GetFontRenderParams().Get());
175 viz_main_ptr_->CreateGpuService(
176 mojo::MakeRequest(&gpu_service_ptr_), std::move(host_proxy),
177 std::move(discardable_manager_ptr), activity_flags_.CloneHandle(),
178 GetFontRenderParams().Get()->subpixel_rendering);
Mohsen Izadi63d85e72018-09-06 16:00:21179
180#if defined(USE_OZONE)
181 InitOzone();
182#endif // defined(USE_OZONE)
Mohsen Izadi0b9fbb62018-08-30 20:30:00183}
184
Mohsen Izadif9505d82018-10-06 01:34:03185GpuHostImpl::~GpuHostImpl() {
186 SendOutstandingReplies();
187}
Mohsen Izadi0b9fbb62018-08-30 20:30:00188
189// static
190void GpuHostImpl::InitFontRenderParams(const gfx::FontRenderParams& params) {
191 DCHECK(!GetFontRenderParams().Get());
192 GetFontRenderParams().Set(params);
193}
194
Mohsen Izadif9505d82018-10-06 01:34:03195// static
196void GpuHostImpl::ResetFontRenderParams() {
197 DCHECK(GetFontRenderParams().Get());
198 GetFontRenderParams().Reset();
199}
200
Mohsen Izadi0b9fbb62018-08-30 20:30:00201void GpuHostImpl::OnProcessLaunched(base::ProcessId pid) {
202 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
203 DCHECK_EQ(base::kNullProcessId, pid_);
204 DCHECK_NE(base::kNullProcessId, pid);
205 pid_ = pid;
206}
207
208void GpuHostImpl::OnProcessCrashed() {
209 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
210
211 // If the GPU process crashed while compiling a shader, we may have invalid
212 // cached binaries. Completely clear the shader cache to force shader binaries
213 // to be re-created.
214 if (activity_flags_.IsFlagSet(
215 gpu::ActivityFlagsBase::FLAG_LOADING_PROGRAM_BINARY)) {
216 auto* shader_cache_factory = delegate_->GetShaderCacheFactory();
217 for (auto cache_key : client_id_to_shader_cache_) {
218 // This call will temporarily extend the lifetime of the cache (kept
219 // alive in the factory), and may drop loads of cached shader binaries if
220 // it takes a while to complete. As we are intentionally dropping all
221 // binaries, this behavior is fine.
222 shader_cache_factory->ClearByClientId(
223 cache_key.first, base::Time(), base::Time::Max(), base::DoNothing());
224 }
225 }
226}
227
Mohsen Izadibabed2b2018-08-31 01:37:39228void GpuHostImpl::AddConnectionErrorHandler(base::OnceClosure handler) {
229 connection_error_handlers_.push_back(std::move(handler));
230}
231
Mohsen Izadi0b9fbb62018-08-30 20:30:00232void GpuHostImpl::BlockLiveOffscreenContexts() {
233 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
234
235 for (auto iter = urls_with_live_offscreen_contexts_.begin();
236 iter != urls_with_live_offscreen_contexts_.end(); ++iter) {
Mohsen Izadi312c6922018-09-07 14:21:36237 delegate_->BlockDomainFrom3DAPIs(*iter, gpu::DomainGuilt::kUnknown);
Mohsen Izadi0b9fbb62018-08-30 20:30:00238 }
239}
240
241void GpuHostImpl::ConnectFrameSinkManager(
242 mojom::FrameSinkManagerRequest request,
243 mojom::FrameSinkManagerClientPtrInfo client) {
244 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
245 TRACE_EVENT0("gpu", "GpuHostImpl::ConnectFrameSinkManager");
246
247 mojom::FrameSinkManagerParamsPtr params =
248 mojom::FrameSinkManagerParams::New();
249 params->restart_id = params_.restart_id;
250 params->use_activation_deadline =
251 params_.deadline_to_synchronize_surfaces.has_value();
252 params->activation_deadline_in_frames =
253 params_.deadline_to_synchronize_surfaces.value_or(0u);
254 params->frame_sink_manager = std::move(request);
255 params->frame_sink_manager_client = std::move(client);
256 viz_main_ptr_->CreateFrameSinkManager(std::move(params));
257}
258
259void GpuHostImpl::EstablishGpuChannel(int client_id,
260 uint64_t client_tracing_id,
261 bool is_gpu_host,
262 EstablishChannelCallback callback) {
263 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
264 TRACE_EVENT0("gpu", "GpuHostImpl::EstablishGpuChannel");
265
266 // If GPU features are already blacklisted, no need to establish the channel.
267 if (!delegate_->GpuAccessAllowed()) {
268 DVLOG(1) << "GPU blacklisted, refusing to open a GPU channel.";
269 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
270 gpu::GpuFeatureInfo(),
271 EstablishChannelStatus::kGpuAccessDenied);
272 return;
273 }
274
275 if (gpu::IsReservedClientId(client_id)) {
276 // The display-compositor/GrShaderCache in the gpu process uses these
277 // special client ids.
278 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
279 gpu::GpuFeatureInfo(),
280 EstablishChannelStatus::kGpuAccessDenied);
281 return;
282 }
283
284 bool cache_shaders_on_disk =
285 delegate_->GetShaderCacheFactory()->Get(client_id) != nullptr;
286
287 channel_requests_.push(std::move(callback));
288 gpu_service_ptr_->EstablishGpuChannel(
289 client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk,
290 base::BindOnce(&GpuHostImpl::OnChannelEstablished,
291 weak_ptr_factory_.GetWeakPtr(), client_id));
292
293 if (!params_.disable_gpu_shader_disk_cache) {
294 CreateChannelCache(client_id);
295
296 bool oopd_enabled =
297 base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
298 if (oopd_enabled)
299 CreateChannelCache(gpu::kInProcessCommandBufferClientId);
300
301 bool oopr_enabled =
302 base::FeatureList::IsEnabled(features::kDefaultEnableOopRasterization);
303 if (oopr_enabled)
304 CreateChannelCache(gpu::kGrShaderCacheClientId);
305 }
306}
307
308void GpuHostImpl::SendOutstandingReplies() {
309 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
310
Mohsen Izadibabed2b2018-08-31 01:37:39311 for (auto& handler : connection_error_handlers_)
312 std::move(handler).Run();
313 connection_error_handlers_.clear();
314
Mohsen Izadi0b9fbb62018-08-30 20:30:00315 // Send empty channel handles for all EstablishChannel requests.
316 while (!channel_requests_.empty()) {
317 auto callback = std::move(channel_requests_.front());
318 channel_requests_.pop();
319 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
320 gpu::GpuFeatureInfo(),
321 EstablishChannelStatus::kGpuHostInvalid);
322 }
323}
324
Mohsen Izadi63d85e72018-09-06 16:00:21325void GpuHostImpl::BindInterface(const std::string& interface_name,
326 mojo::ScopedMessagePipeHandle interface_pipe) {
327 delegate_->BindInterface(interface_name, std::move(interface_pipe));
328}
329
Mohsen Izadi0b9fbb62018-08-30 20:30:00330mojom::GpuService* GpuHostImpl::gpu_service() {
331 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
332 DCHECK(gpu_service_ptr_.is_bound());
333 return gpu_service_ptr_.get();
334}
335
Mohsen Izadi63d85e72018-09-06 16:00:21336#if defined(USE_OZONE)
337void GpuHostImpl::InitOzone() {
338 // Ozone needs to send the primary DRM device to GPU service as early as
339 // possible to ensure the latter always has a valid device.
340 // https://crbug.com/608839
341 // If the OzonePlatform is not created yet, defer the callback until
342 // OzonePlatform instance is created.
Maksim Sisov2e064342018-10-03 10:35:06343 //
344 // The Ozone/Wayland requires mojo communication to be established to be
345 // functional with a separate gpu process. Thus, using the PlatformProperties,
346 // check if there is such a requirement.
347 if (features::IsOzoneDrmMojo() || ui::OzonePlatform::EnsureInstance()
348 ->GetPlatformProperties()
349 .requires_mojo) {
Mohsen Izadi63d85e72018-09-06 16:00:21350 // TODO(rjkroege): Remove the legacy IPC code paths when no longer
351 // necessary. https://crbug.com/806092
352 auto interface_binder = base::BindRepeating(&GpuHostImpl::BindInterface,
353 weak_ptr_factory_.GetWeakPtr());
354 auto terminate_callback = base::BindOnce(&GpuHostImpl::TerminateGpuProcess,
355 weak_ptr_factory_.GetWeakPtr());
356
357 auto startup_callback = base::BindOnce(
358 [](const base::RepeatingCallback<void(const std::string&,
359 mojo::ScopedMessagePipeHandle)>&
360 interface_binder,
361 base::OnceCallback<void(const std::string&)> terminate_callback,
362 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
363 scoped_refptr<base::SingleThreadTaskRunner> host_thread_task_runner,
364 ui::OzonePlatform* platform) {
365 DCHECK(host_thread_task_runner->BelongsToCurrentThread());
366 platform->GetGpuPlatformSupportHost()->OnGpuServiceLaunched(
367 main_thread_task_runner, host_thread_task_runner,
368 interface_binder, std::move(terminate_callback));
369 },
370 interface_binder, std::move(terminate_callback),
371 params_.main_thread_task_runner, host_thread_task_runner_);
372 OzoneRegisterStartupCallbackHelper(host_thread_task_runner_,
373 std::move(startup_callback));
374 } else {
375 auto send_callback = base::BindRepeating(
376 [](base::WeakPtr<GpuHostImpl> host, IPC::Message* message) {
377 if (host)
378 host->delegate_->SendGpuProcessMessage(message);
379 else
380 delete message;
381 },
382 weak_ptr_factory_.GetWeakPtr());
383 // Create the callback that should run on the current thread.
384 auto startup_callback = base::BindOnce(
385 [](int host_id,
386 const base::RepeatingCallback<void(IPC::Message*)>& send_callback,
387 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
388 scoped_refptr<base::SingleThreadTaskRunner> host_thread_task_runner,
389 ui::OzonePlatform* platform) {
390 DCHECK(host_thread_task_runner->BelongsToCurrentThread());
391 platform->GetGpuPlatformSupportHost()->OnGpuProcessLaunched(
392 host_id, main_thread_task_runner, host_thread_task_runner,
393 send_callback);
394 },
395 params_.restart_id, send_callback, params_.main_thread_task_runner,
396 host_thread_task_runner_);
397 OzoneRegisterStartupCallbackHelper(host_thread_task_runner_,
398 std::move(startup_callback));
399 }
400}
401
402void GpuHostImpl::TerminateGpuProcess(const std::string& message) {
403 delegate_->TerminateGpuProcess(message);
404}
405
406#endif // defined(USE_OZONE)
407
Mohsen Izadi0b9fbb62018-08-30 20:30:00408std::string GpuHostImpl::GetShaderPrefixKey() {
409 if (shader_prefix_key_.empty()) {
410 const gpu::GPUInfo& info = delegate_->GetGPUInfo();
411 const gpu::GPUInfo::GPUDevice& active_gpu = info.active_gpu();
412
413 shader_prefix_key_ = params_.product + "-" + info.gl_vendor + "-" +
414 info.gl_renderer + "-" + active_gpu.driver_version +
415 "-" + active_gpu.driver_vendor;
416
417#if defined(OS_ANDROID)
418 std::string build_fp =
419 base::android::BuildInfo::GetInstance()->android_build_fp();
Mohsen Izadi0b9fbb62018-08-30 20:30:00420 shader_prefix_key_ += "-" + build_fp;
421#endif
422 }
423
424 return shader_prefix_key_;
425}
426
427void GpuHostImpl::LoadedShader(int32_t client_id,
428 const std::string& key,
429 const std::string& data) {
430 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
431
432 std::string prefix = GetShaderPrefixKey();
433 bool prefix_ok = !key.compare(0, prefix.length(), prefix);
434 UMA_HISTOGRAM_BOOLEAN("GPU.ShaderLoadPrefixOK", prefix_ok);
435 if (prefix_ok) {
436 // Remove the prefix from the key before load.
437 std::string key_no_prefix = key.substr(prefix.length() + 1);
438 gpu_service_ptr_->LoadedShader(client_id, key_no_prefix, data);
439 }
440}
441
442void GpuHostImpl::CreateChannelCache(int32_t client_id) {
443 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
444 TRACE_EVENT0("gpu", "GpuHostImpl::CreateChannelCache");
445
446 scoped_refptr<gpu::ShaderDiskCache> cache =
447 delegate_->GetShaderCacheFactory()->Get(client_id);
448 if (!cache)
449 return;
450
451 cache->set_shader_loaded_callback(base::BindRepeating(
452 &GpuHostImpl::LoadedShader, weak_ptr_factory_.GetWeakPtr(), client_id));
453
454 client_id_to_shader_cache_[client_id] = cache;
455}
456
457void GpuHostImpl::OnChannelEstablished(
458 int client_id,
459 mojo::ScopedMessagePipeHandle channel_handle) {
460 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
461 TRACE_EVENT0("gpu", "GpuHostImpl::OnChannelEstablished");
462
463 DCHECK(!channel_requests_.empty());
464 auto callback = std::move(channel_requests_.front());
465 channel_requests_.pop();
466
467 // Currently if any of the GPU features are blacklisted, we don't establish a
468 // GPU channel.
469 if (channel_handle.is_valid() && !delegate_->GpuAccessAllowed()) {
470 gpu_service_ptr_->CloseChannel(client_id);
471 std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
472 gpu::GpuFeatureInfo(),
473 EstablishChannelStatus::kGpuAccessDenied);
474 RecordLogMessage(logging::LOG_WARNING, "WARNING",
475 "Hardware acceleration is unavailable.");
476 return;
477 }
478
479 std::move(callback).Run(std::move(channel_handle), delegate_->GetGPUInfo(),
480 delegate_->GetGpuFeatureInfo(),
481 EstablishChannelStatus::kSuccess);
482}
483
484void GpuHostImpl::DidInitialize(
485 const gpu::GPUInfo& gpu_info,
486 const gpu::GpuFeatureInfo& gpu_feature_info,
487 const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
488 const base::Optional<gpu::GpuFeatureInfo>&
489 gpu_feature_info_for_hardware_gpu) {
490 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", true);
491 initialized_ = true;
492
493 // Set GPU driver bug workaround flags that are checked on the browser side.
494 wake_up_gpu_before_drawing_ =
495 gpu_feature_info.IsWorkaroundEnabled(gpu::WAKE_UP_GPU_BEFORE_DRAWING);
496 dont_disable_webgl_when_compositor_context_lost_ =
497 gpu_feature_info.IsWorkaroundEnabled(
498 gpu::DONT_DISABLE_WEBGL_WHEN_COMPOSITOR_CONTEXT_LOST);
499
Mohsen Izadif9505d82018-10-06 01:34:03500 delegate_->DidInitialize(gpu_info, gpu_feature_info,
Mohsen Izadi0b9fbb62018-08-30 20:30:00501 gpu_info_for_hardware_gpu,
502 gpu_feature_info_for_hardware_gpu);
503}
504
505void GpuHostImpl::DidFailInitialize() {
506 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", false);
507 delegate_->DidFailInitialize();
508}
509
510void GpuHostImpl::DidCreateContextSuccessfully() {
511 delegate_->DidCreateContextSuccessfully();
512}
513
514void GpuHostImpl::DidCreateOffscreenContext(const GURL& url) {
515 urls_with_live_offscreen_contexts_.insert(url);
516}
517
518void GpuHostImpl::DidDestroyOffscreenContext(const GURL& url) {
519 // We only want to remove *one* of the entries in the multiset for this
520 // particular URL, so can't use the erase method taking a key.
521 auto candidate = urls_with_live_offscreen_contexts_.find(url);
522 if (candidate != urls_with_live_offscreen_contexts_.end())
523 urls_with_live_offscreen_contexts_.erase(candidate);
524}
525
526void GpuHostImpl::DidDestroyChannel(int32_t client_id) {
527 TRACE_EVENT0("gpu", "GpuHostImpl::DidDestroyChannel");
528 client_id_to_shader_cache_.erase(client_id);
529}
530
531void GpuHostImpl::DidLoseContext(bool offscreen,
532 gpu::error::ContextLostReason reason,
533 const GURL& active_url) {
534 // TODO(kbr): would be nice to see the "offscreen" flag too.
535 TRACE_EVENT2("gpu", "GpuHostImpl::DidLoseContext", "reason", reason, "url",
536 active_url.possibly_invalid_spec());
537
538 if (!offscreen || active_url.is_empty()) {
539 // Assume that the loss of the compositor's or accelerated canvas'
540 // context is a serious event and blame the loss on all live
541 // offscreen contexts. This more robustly handles situations where
542 // the GPU process may not actually detect the context loss in the
543 // offscreen context. However, situations have been seen where the
544 // compositor's context can be lost due to driver bugs (as of this
545 // writing, on Android), so allow that possibility.
546 if (!dont_disable_webgl_when_compositor_context_lost_)
547 BlockLiveOffscreenContexts();
548 return;
549 }
550
Mohsen Izadi312c6922018-09-07 14:21:36551 gpu::DomainGuilt guilt = gpu::DomainGuilt::kUnknown;
Mohsen Izadi0b9fbb62018-08-30 20:30:00552 switch (reason) {
553 case gpu::error::kGuilty:
Mohsen Izadi312c6922018-09-07 14:21:36554 guilt = gpu::DomainGuilt::kKnown;
Mohsen Izadi0b9fbb62018-08-30 20:30:00555 break;
556 // Treat most other error codes as though they had unknown provenance.
557 // In practice this doesn't affect the user experience. A lost context
558 // of either known or unknown guilt still causes user-level 3D APIs
559 // (e.g. WebGL) to be blocked on that domain until the user manually
560 // reenables them.
561 case gpu::error::kUnknown:
562 case gpu::error::kOutOfMemory:
563 case gpu::error::kMakeCurrentFailed:
564 case gpu::error::kGpuChannelLost:
565 case gpu::error::kInvalidGpuMessage:
566 break;
567 case gpu::error::kInnocent:
568 return;
569 }
570
571 delegate_->BlockDomainFrom3DAPIs(active_url, guilt);
572}
573
574void GpuHostImpl::DisableGpuCompositing() {
575 delegate_->DisableGpuCompositing();
576}
577
Mohsen Izadi50c28052018-09-07 00:32:14578#if defined(OS_WIN)
Mohsen Izadi0b9fbb62018-08-30 20:30:00579void GpuHostImpl::SetChildSurface(gpu::SurfaceHandle parent,
580 gpu::SurfaceHandle child) {
kylechar89341da82018-09-10 15:26:27581 if (pid_ != base::kNullProcessId) {
582 gfx::RenderingWindowManager::GetInstance()->RegisterChild(
583 parent, child, /*expected_child_process_id=*/pid_);
Mohsen Izadi0b9fbb62018-08-30 20:30:00584 }
Mohsen Izadi0b9fbb62018-08-30 20:30:00585}
Mohsen Izadi50c28052018-09-07 00:32:14586#endif // defined(OS_WIN)
Mohsen Izadi0b9fbb62018-08-30 20:30:00587
588void GpuHostImpl::StoreShaderToDisk(int32_t client_id,
589 const std::string& key,
590 const std::string& shader) {
591 TRACE_EVENT0("gpu", "GpuHostImpl::StoreShaderToDisk");
592 auto iter = client_id_to_shader_cache_.find(client_id);
593 // If the cache doesn't exist then this is an off the record profile.
594 if (iter == client_id_to_shader_cache_.end())
595 return;
596 std::string prefix = GetShaderPrefixKey();
597 iter->second->Cache(prefix + ":" + key, shader);
598}
599
600void GpuHostImpl::RecordLogMessage(int32_t severity,
601 const std::string& header,
602 const std::string& message) {
603 delegate_->RecordLogMessage(severity, header, message);
604}
605
606} // namespace viz