Commit 0ab7fb0d authored by kylechar's avatar kylechar Committed by Commit Bot

viz: Fix software compositing fallback.

Add some missing cases where we want to fallback on software compositing
to VizProcessTransportFactory.

1. When GPU_FEATURE_TYPE_GPU_COMPOSITING is blacklisted in
   GpuFeatureInfo.
2. When ContextProvider creation fatally fails.

This CL also cleans up the logic to make it easier to follow and removes
an unnecessary subclass from VizProcessTransportFactory.

Bug: 776050
Change-Id: I7d0e65ac224e649cad786246486fc40c9c841f27
Reviewed-on: https://chromium-review.googlesource.com/1030829
Commit-Queue: kylechar <kylechar@chromium.org>
Reviewed-by: default avatardanakj <danakj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554538}
parent 4d425c09
...@@ -653,6 +653,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ...@@ -653,6 +653,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
void GpuProcessTransportFactory::DisableGpuCompositing( void GpuProcessTransportFactory::DisableGpuCompositing(
ui::Compositor* guilty_compositor) { ui::Compositor* guilty_compositor) {
DLOG(ERROR) << "Switching to software compositing.";
// Change the result of IsGpuCompositingDisabled() before notifying anything. // Change the result of IsGpuCompositingDisabled() before notifying anything.
is_gpu_compositing_disabled_ = true; is_gpu_compositing_disabled_ = true;
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/common/context_result.h"
#include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/client/gpu_channel_host.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/compositor/reflector.h" #include "ui/compositor/reflector.h"
...@@ -129,7 +128,7 @@ VizProcessTransportFactory::VizProcessTransportFactory( ...@@ -129,7 +128,7 @@ VizProcessTransportFactory::VizProcessTransportFactory(
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableGpu) || if (command_line->HasSwitch(switches::kDisableGpu) ||
command_line->HasSwitch(switches::kDisableGpuCompositing)) { command_line->HasSwitch(switches::kDisableGpuCompositing)) {
CompositingModeFallbackToSoftware(); DisableGpuCompositing(nullptr);
} }
} }
...@@ -196,8 +195,15 @@ VizProcessTransportFactory::SharedMainThreadContextProvider() { ...@@ -196,8 +195,15 @@ VizProcessTransportFactory::SharedMainThreadContextProvider() {
return nullptr; return nullptr;
if (!main_context_provider_) { if (!main_context_provider_) {
CreateContextProviders( auto context_result = gpu::ContextResult::kTransientFailure;
gpu_channel_establish_factory_->EstablishGpuChannelSync()); while (context_result == gpu::ContextResult::kTransientFailure) {
context_result = TryCreateContextsForGpuCompositing(
gpu_channel_establish_factory_->EstablishGpuChannelSync());
if (context_result == gpu::ContextResult::kFatalFailure)
DisableGpuCompositing(nullptr);
}
// On kFatalFailure |main_context_provider_| will be null.
} }
return main_context_provider_; return main_context_provider_;
...@@ -360,11 +366,16 @@ viz::GLHelper* VizProcessTransportFactory::GetGLHelper() { ...@@ -360,11 +366,16 @@ viz::GLHelper* VizProcessTransportFactory::GetGLHelper() {
return nullptr; return nullptr;
} }
void VizProcessTransportFactory::CompositingModeFallbackToSoftware() { void VizProcessTransportFactory::OnContextLost() {
// This may happen multiple times, since when the viz process (re)starts, it base::ThreadTaskRunnerHandle::Get()->PostTask(
// will send this notification if gpu is disabled. FROM_HERE,
if (is_gpu_compositing_disabled_) base::BindOnce(&VizProcessTransportFactory::OnLostMainThreadSharedContext,
return; weak_ptr_factory_.GetWeakPtr()));
}
void VizProcessTransportFactory::DisableGpuCompositing(
ui::Compositor* guilty_compositor) {
DLOG(ERROR) << "Switching to software compositing.";
// Change the result of IsGpuCompositingDisabled() before notifying anything. // Change the result of IsGpuCompositingDisabled() before notifying anything.
is_gpu_compositing_disabled_ = true; is_gpu_compositing_disabled_ = true;
...@@ -394,8 +405,15 @@ void VizProcessTransportFactory::CompositingModeFallbackToSoftware() { ...@@ -394,8 +405,15 @@ void VizProcessTransportFactory::CompositingModeFallbackToSoftware() {
to_release.reserve(compositor_data_map_.size()); to_release.reserve(compositor_data_map_.size());
for (auto& pair : compositor_data_map_) { for (auto& pair : compositor_data_map_) {
ui::Compositor* compositor = pair.first; ui::Compositor* compositor = pair.first;
if (!compositor->force_software_compositor()) // The |guilty_compositor| is in the process of setting up its FrameSink
// so removing it from |compositor_data_map_| would be both pointless and
// the cause of a crash.
// Compositors with force_software_compositor() do not follow the global
// compositing mode, so they do not need to changed.
if (compositor != guilty_compositor &&
!compositor->force_software_compositor()) {
to_release.push_back(compositor); to_release.push_back(compositor);
}
} }
for (ui::Compositor* compositor : to_release) { for (ui::Compositor* compositor : to_release) {
// Compositor expects to be not visible when releasing its FrameSink. // Compositor expects to be not visible when releasing its FrameSink.
...@@ -410,13 +428,6 @@ void VizProcessTransportFactory::CompositingModeFallbackToSoftware() { ...@@ -410,13 +428,6 @@ void VizProcessTransportFactory::CompositingModeFallbackToSoftware() {
GpuDataManagerImpl::GetInstance()->NotifyGpuInfoUpdate(); GpuDataManagerImpl::GetInstance()->NotifyGpuInfoUpdate();
} }
void VizProcessTransportFactory::OnContextLost() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&VizProcessTransportFactory::OnLostMainThreadSharedContext,
weak_ptr_factory_.GetWeakPtr()));
}
void VizProcessTransportFactory::OnGpuProcessLost() { void VizProcessTransportFactory::OnGpuProcessLost() {
// Reconnect HostFrameSinkManager to new GPU process. // Reconnect HostFrameSinkManager to new GPU process.
ConnectHostFrameSinkManager(); ConnectHostFrameSinkManager();
...@@ -432,18 +443,18 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel( ...@@ -432,18 +443,18 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
bool gpu_compositing = bool gpu_compositing =
!is_gpu_compositing_disabled_ && !compositor->force_software_compositor(); !is_gpu_compositing_disabled_ && !compositor->force_software_compositor();
// Only try to make contexts for gpu compositing.
if (gpu_compositing) { if (gpu_compositing) {
// TODO(kylechar): Check GPU compositing status from GpuFeatureInfo. auto context_result =
TryCreateContextsForGpuCompositing(std::move(gpu_channel_host));
if (!gpu_channel_host || if (context_result == gpu::ContextResult::kTransientFailure) {
!CreateContextProviders(std::move(gpu_channel_host))) { // Get a new GpuChannelHost and retry context creation.
// Retry on failure. If this isn't possible we should hear that we're
// falling back to software compositing from the viz process eventually.
gpu_channel_establish_factory_->EstablishGpuChannel( gpu_channel_establish_factory_->EstablishGpuChannel(
base::BindOnce(&VizProcessTransportFactory::OnEstablishedGpuChannel, base::BindOnce(&VizProcessTransportFactory::OnEstablishedGpuChannel,
weak_ptr_factory_.GetWeakPtr(), compositor_weak_ptr)); weak_ptr_factory_.GetWeakPtr(), compositor_weak_ptr));
return; return;
} else if (context_result == gpu::ContextResult::kFatalFailure) {
DisableGpuCompositing(compositor);
gpu_compositing = false;
} }
} }
...@@ -530,27 +541,32 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel( ...@@ -530,27 +541,32 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
#endif #endif
} }
bool VizProcessTransportFactory::CreateContextProviders( gpu::ContextResult
VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
constexpr bool kSharedWorkerContextSupportsLocking = true; DCHECK(!is_gpu_compositing_disabled_);
constexpr bool kSharedWorkerContextSupportsGLES2 = false;
constexpr bool kSharedWorkerContextSupportsRaster = true;
constexpr bool kSharedWorkerContextSupportsGrContext = false;
constexpr bool kCompositorContextSupportsLocking = false;
constexpr bool kCompositorContextSupportsGLES2 = true;
constexpr bool kCompositorContextSupportsRaster = false;
constexpr bool kCompositorContextSupportsGrContext = true;
if (main_context_provider_ && IsContextLost(main_context_provider_.get())) { // Fallback to software compositing if there is no IPC channel.
main_context_provider_->RemoveObserver(this); if (!gpu_channel_host)
main_context_provider_ = nullptr; return gpu::ContextResult::kFatalFailure;
}
// Fallback to software compositing if GPU compositing is blacklisted.
auto gpu_compositing_status =
gpu_channel_host->gpu_feature_info()
.status_values[gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING];
if (gpu_compositing_status != gpu::kGpuFeatureStatusEnabled)
return gpu::ContextResult::kFatalFailure;
if (worker_context_provider_ && if (worker_context_provider_ &&
IsWorkerContextLost(worker_context_provider_.get())) IsWorkerContextLost(worker_context_provider_.get()))
worker_context_provider_ = nullptr; worker_context_provider_ = nullptr;
if (!worker_context_provider_) { if (!worker_context_provider_) {
constexpr bool kSharedWorkerContextSupportsLocking = true;
constexpr bool kSharedWorkerContextSupportsGLES2 = false;
constexpr bool kSharedWorkerContextSupportsRaster = true;
constexpr bool kSharedWorkerContextSupportsGrContext = false;
worker_context_provider_ = CreateContextProviderImpl( worker_context_provider_ = CreateContextProviderImpl(
gpu_channel_host, GetGpuMemoryBufferManager(), gpu_channel_host, GetGpuMemoryBufferManager(),
kSharedWorkerContextSupportsLocking, kSharedWorkerContextSupportsGLES2, kSharedWorkerContextSupportsLocking, kSharedWorkerContextSupportsGLES2,
...@@ -561,32 +577,42 @@ bool VizProcessTransportFactory::CreateContextProviders( ...@@ -561,32 +577,42 @@ bool VizProcessTransportFactory::CreateContextProviders(
// Don't observer context loss on |worker_context_provider_| here, that is // Don't observer context loss on |worker_context_provider_| here, that is
// already observered by LayerTreeFrameSink. The lost context will be caught // already observered by LayerTreeFrameSink. The lost context will be caught
// when recreating LayerTreeFrameSink(s). // when recreating LayerTreeFrameSink(s).
auto result = worker_context_provider_->BindToCurrentThread(); auto context_result = worker_context_provider_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) { if (context_result != gpu::ContextResult::kSuccess) {
worker_context_provider_ = nullptr; worker_context_provider_ = nullptr;
return false; return context_result;
} }
} }
if (main_context_provider_ && IsContextLost(main_context_provider_.get())) {
main_context_provider_->RemoveObserver(this);
main_context_provider_ = nullptr;
}
if (!main_context_provider_) { if (!main_context_provider_) {
constexpr bool kCompositorContextSupportsLocking = false;
constexpr bool kCompositorContextSupportsGLES2 = true;
constexpr bool kCompositorContextSupportsRaster = false;
constexpr bool kCompositorContextSupportsGrContext = true;
main_context_provider_ = CreateContextProviderImpl( main_context_provider_ = CreateContextProviderImpl(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(), std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
kCompositorContextSupportsLocking, kCompositorContextSupportsGLES2, kCompositorContextSupportsLocking, kCompositorContextSupportsGLES2,
kCompositorContextSupportsRaster, kCompositorContextSupportsGrContext, kCompositorContextSupportsRaster, kCompositorContextSupportsGrContext,
ui::command_buffer_metrics::UI_COMPOSITOR_CONTEXT); ui::command_buffer_metrics::UI_COMPOSITOR_CONTEXT);
main_context_provider_->SetDefaultTaskRunner(resize_task_runner_); main_context_provider_->SetDefaultTaskRunner(resize_task_runner_);
main_context_provider_->AddObserver(this);
auto result = main_context_provider_->BindToCurrentThread(); auto context_result = main_context_provider_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) { if (context_result != gpu::ContextResult::kSuccess) {
main_context_provider_->RemoveObserver(this);
main_context_provider_ = nullptr;
worker_context_provider_ = nullptr; worker_context_provider_ = nullptr;
return false; main_context_provider_ = nullptr;
return context_result;
} }
main_context_provider_->AddObserver(this);
} }
return true; return gpu::ContextResult::kSuccess;
} }
void VizProcessTransportFactory::OnLostMainThreadSharedContext() { void VizProcessTransportFactory::OnLostMainThreadSharedContext() {
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h"
#include "content/browser/compositor/image_transport_factory.h" #include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/compositor/in_process_display_client.h" #include "content/browser/compositor/in_process_display_client.h"
#include "gpu/command_buffer/common/context_result.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h" #include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "ui/compositor/compositor.h" #include "ui/compositor/compositor.h"
...@@ -53,7 +53,6 @@ class ExternalBeginFrameControllerClientImpl; ...@@ -53,7 +53,6 @@ class ExternalBeginFrameControllerClientImpl;
class VizProcessTransportFactory : public ui::ContextFactory, class VizProcessTransportFactory : public ui::ContextFactory,
public ui::ContextFactoryPrivate, public ui::ContextFactoryPrivate,
public ImageTransportFactory, public ImageTransportFactory,
public viz::mojom::CompositingModeWatcher,
public viz::ContextLostObserver { public viz::ContextLostObserver {
public: public:
VizProcessTransportFactory( VizProcessTransportFactory(
...@@ -107,9 +106,6 @@ class VizProcessTransportFactory : public ui::ContextFactory, ...@@ -107,9 +106,6 @@ class VizProcessTransportFactory : public ui::ContextFactory,
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override; ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
viz::GLHelper* GetGLHelper() override; viz::GLHelper* GetGLHelper() override;
// viz::mojom::CompositingModeWatcher implementation.
void CompositingModeFallbackToSoftware() override;
// viz::ContextLostObserver implementation. // viz::ContextLostObserver implementation.
void OnContextLost() override; void OnContextLost() override;
...@@ -134,6 +130,12 @@ class VizProcessTransportFactory : public ui::ContextFactory, ...@@ -134,6 +130,12 @@ class VizProcessTransportFactory : public ui::ContextFactory,
DISALLOW_COPY_AND_ASSIGN(CompositorData); DISALLOW_COPY_AND_ASSIGN(CompositorData);
}; };
// Disables GPU compositing. This notifies UI and renderer compositors to drop
// LayerTreeFrameSinks and request new ones. If fallback happens while
// creating a new LayerTreeFrameSink for UI compositor it should be passed in
// as |guilty_compositor| to avoid extra work and reentrancy problems.
void DisableGpuCompositing(ui::Compositor* guilty_compositor);
// Provided as a callback when the GPU process has crashed. // Provided as a callback when the GPU process has crashed.
void OnGpuProcessLost(); void OnGpuProcessLost();
...@@ -143,10 +145,15 @@ class VizProcessTransportFactory : public ui::ContextFactory, ...@@ -143,10 +145,15 @@ class VizProcessTransportFactory : public ui::ContextFactory,
base::WeakPtr<ui::Compositor> compositor_weak_ptr, base::WeakPtr<ui::Compositor> compositor_weak_ptr,
scoped_refptr<gpu::GpuChannelHost> gpu_channel); scoped_refptr<gpu::GpuChannelHost> gpu_channel);
// Creates the necessary shared worker and compositor ContextProviders. If the // Tries to create the raster and main thread ContextProviders. If the
// ContextProviders already exist and haven't been lost then it will do // ContextProviders already exist and haven't been lost then this will do
// nothing. Returns true if ContextProviders exist. // nothing. Also verifies |gpu_channel_host| and checks if GPU compositing is
bool CreateContextProviders( // blacklisted.
//
// Returns kSuccess if caller can use GPU compositing, kTransientFailure if
// caller should try again or kFatalFailure if caller should fallback to
// software compositing.
gpu::ContextResult TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host); scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
void OnLostMainThreadSharedContext(); void OnLostMainThreadSharedContext();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment