blob: 07502f4ff2afd53a43d8f0ab68d4c4c39f6c0737 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/service/display_embedder/output_surface_provider_impl.h"
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "cc/base/switches.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
#include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
#include "components/viz/service/display_embedder/software_output_surface.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/scheduler_sequence.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/base/ui_base_switches.h"
#if BUILDFLAG(IS_WIN)
#include "components/viz/service/display_embedder/software_output_device_win.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "components/viz/service/display_embedder/software_output_device_mac.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "ui/base/cocoa/remote_layer_api.h"
#endif
#if BUILDFLAG(IS_OZONE)
#include "components/viz/service/display_embedder/software_output_device_ozone.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/platform_window_surface.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#include "ui/ozone/public/surface_ozone_canvas.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "components/viz/service/display_embedder/output_surface_unified.h"
#endif
namespace viz {
OutputSurfaceProviderImpl::OutputSurfaceProviderImpl(
GpuServiceImpl* gpu_service_impl,
bool headless)
: gpu_service_impl_(gpu_service_impl),
task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()),
headless_(headless) {}
OutputSurfaceProviderImpl::OutputSurfaceProviderImpl(bool headless)
: OutputSurfaceProviderImpl(
/*gpu_service_impl=*/nullptr,
headless) {}
OutputSurfaceProviderImpl::~OutputSurfaceProviderImpl() = default;
std::unique_ptr<DisplayCompositorMemoryAndTaskController>
OutputSurfaceProviderImpl::CreateGpuDependency(
bool gpu_compositing,
gpu::SurfaceHandle surface_handle) {
if (!gpu_compositing)
return nullptr;
gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
auto skia_deps = std::make_unique<SkiaOutputSurfaceDependencyImpl>(
gpu_service_impl_, surface_handle);
return std::make_unique<DisplayCompositorMemoryAndTaskController>(
std::move(skia_deps));
}
std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
gpu::SurfaceHandle surface_handle,
bool gpu_compositing,
mojom::DisplayClient* display_client,
DisplayCompositorMemoryAndTaskController* gpu_dependency,
const RendererSettings& renderer_settings,
const DebugRendererSettings* debug_settings) {
#if BUILDFLAG(IS_CHROMEOS)
if (surface_handle == gpu::kNullSurfaceHandle)
return std::make_unique<OutputSurfaceUnified>();
#endif
if (!gpu_compositing) {
return std::make_unique<SoftwareOutputSurface>(
CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client));
} else {
DCHECK(gpu_dependency);
std::unique_ptr<OutputSurface> output_surface;
{
gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
output_surface = SkiaOutputSurfaceImpl::Create(
gpu_dependency, renderer_settings, debug_settings);
}
#if BUILDFLAG(IS_ANDROID)
// As with non-skia-renderer case, communicate the creation result to
// CompositorImplAndroid so that it can attempt to recreate the surface on
// failure.
display_client->OnContextCreationResult(
output_surface ? gpu::ContextResult::kSuccess
: gpu::ContextResult::kSurfaceFailure);
#endif // BUILDFLAG(IS_ANDROID)
if (!output_surface) {
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_CASTOS)
// GPU compositing is expected to always work on Chrome OS and Cast
// devices, so we should never encounter fatal context error. This could
// be an unrecoverable hardware error or a bug.
LOG(FATAL) << "Unexpected fatal context error";
#elif !BUILDFLAG(IS_ANDROID)
gpu_service_impl_->DisableGpuCompositing();
#endif
}
return output_surface;
}
}
std::unique_ptr<SoftwareOutputDevice>
OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
gpu::SurfaceHandle surface_handle,
mojom::DisplayClient* display_client) {
if (headless_)
return std::make_unique<SoftwareOutputDevice>();
#if BUILDFLAG(IS_WIN)
HWND child_hwnd;
auto device = CreateSoftwareOutputDeviceWin(
surface_handle, &output_device_backing_, display_client, child_hwnd);
if (child_hwnd) {
display_client->AddChildWindowToBrowser(child_hwnd);
}
return device;
#elif BUILDFLAG(IS_APPLE)
return std::make_unique<SoftwareOutputDeviceMac>(task_runner_);
#elif BUILDFLAG(IS_ANDROID)
// Android does not do software compositing, so we can't get here.
NOTREACHED();
#elif BUILDFLAG(IS_OZONE)
ui::SurfaceFactoryOzone* factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
std::unique_ptr<ui::PlatformWindowSurface> platform_window_surface =
factory->CreatePlatformWindowSurface(surface_handle);
std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone =
factory->CreateCanvasForWidget(surface_handle);
CHECK(surface_ozone);
return std::make_unique<SoftwareOutputDeviceOzone>(
std::move(platform_window_surface), std::move(surface_ozone));
#else
NOTREACHED();
#endif
}
gpu::SharedImageManager* OutputSurfaceProviderImpl::GetSharedImageManager() {
return gpu_service_impl_->shared_image_manager();
}
gpu::SyncPointManager* OutputSurfaceProviderImpl::GetSyncPointManager() {
return gpu_service_impl_->sync_point_manager();
}
gpu::Scheduler* OutputSurfaceProviderImpl::GetGpuScheduler() {
return gpu_service_impl_->gpu_scheduler();
}
} // namespace viz