[go: nahoru, domu]

blob: d39e1fbaa78cfb142d900fa483449e606aa2c5f0 [file] [log] [blame]
// Copyright 2018 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 "components/viz/service/main/viz_compositor_thread_runner_impl.h"
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/message_loop/message_pump_type.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/bind_post_task.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "components/viz/common/switches.h"
#include "components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h"
#include "components/viz/service/display_embedder/output_surface_provider_impl.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/frame_sinks/gmb_video_frame_pool_context_provider_impl.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "components/viz/service/performance_hint/hint_session.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/ipc/command_buffer_task_executor.h"
#include "gpu/ipc/scheduler_sequence.h"
#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
#include "ui/gfx/switches.h"
#if defined(USE_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif
namespace viz {
namespace {
const char kThreadName[] = "VizCompositorThread";
std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread() {
const base::ThreadPriority thread_priority =
base::FeatureList::IsEnabled(features::kGpuUseDisplayThreadPriority)
? base::ThreadPriority::DISPLAY
: base::ThreadPriority::NORMAL;
#if BUILDFLAG(IS_ANDROID)
auto thread = std::make_unique<base::android::JavaHandlerThread>(
kThreadName, thread_priority);
thread->Start();
return thread;
#else // !BUILDFLAG(IS_ANDROID)
std::unique_ptr<base::Thread> thread;
base::Thread::Options thread_options;
#if defined(USE_OZONE)
auto* platform = ui::OzonePlatform::GetInstance();
thread_options.message_pump_type =
platform->GetPlatformProperties().message_pump_type_for_viz_compositor;
thread = std::make_unique<base::Thread>(kThreadName);
#endif
if (!thread)
thread = std::make_unique<base::Thread>(kThreadName);
#if BUILDFLAG(IS_FUCHSIA)
// An IO message pump is needed to use FIDL.
thread_options.message_pump_type = base::MessagePumpType::IO;
#endif
#if BUILDFLAG(IS_APPLE)
// Increase the thread priority to get more reliable values in performance
// test of macOS.
thread_options.priority =
(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseHighGPUThreadPriorityForPerfTests))
? base::ThreadPriority::REALTIME_AUDIO
: thread_priority;
#else
thread_options.priority = thread_priority;
#endif // !BUILDFLAG(IS_APPLE)
CHECK(thread->StartWithOptions(std::move(thread_options)));
// Setup tracing sampler profiler as early as possible.
thread->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&tracing::TracingSamplerProfiler::CreateOnChildThread));
return thread;
#endif // !BUILDFLAG(IS_ANDROID)
}
} // namespace
VizCompositorThreadRunnerImpl::VizCompositorThreadRunnerImpl()
: thread_(CreateAndStartCompositorThread()),
task_runner_(thread_->task_runner()) {}
VizCompositorThreadRunnerImpl::~VizCompositorThreadRunnerImpl() {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VizCompositorThreadRunnerImpl::TearDownOnCompositorThread,
base::Unretained(this)));
thread_->Stop();
}
bool VizCompositorThreadRunnerImpl::CreateHintSessionFactory(
base::flat_set<base::PlatformThreadId> thread_ids,
base::RepeatingClosure* wake_up_closure) {
base::WaitableEvent event;
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VizCompositorThreadRunnerImpl::
CreateHintSessionFactoryOnCompositorThread,
base::Unretained(this), std::move(thread_ids),
wake_up_closure, &event));
event.Wait();
return !!*wake_up_closure;
}
void VizCompositorThreadRunnerImpl::CreateHintSessionFactoryOnCompositorThread(
base::flat_set<base::PlatformThreadId> thread_ids,
base::RepeatingClosure* wake_up_closure,
base::WaitableEvent* event) {
thread_ids.insert(base::PlatformThread::CurrentId());
auto hint_session_factory = HintSessionFactory::Create(std::move(thread_ids));
// Written this way so finch only considers the experiment active on device
// which supports hint session.
if (hint_session_factory && features::IsAdpfEnabled()) {
hint_session_factory_ = std::move(hint_session_factory);
*wake_up_closure = base::BindPostTask(
task_runner_,
base::BindRepeating(
&VizCompositorThreadRunnerImpl::WakeUpOnCompositorThread,
weak_factory_.GetWeakPtr()));
}
event->Signal();
}
void VizCompositorThreadRunnerImpl::WakeUpOnCompositorThread() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (hint_session_factory_)
hint_session_factory_->WakeUp();
}
base::SingleThreadTaskRunner* VizCompositorThreadRunnerImpl::task_runner() {
return task_runner_.get();
}
void VizCompositorThreadRunnerImpl::CreateFrameSinkManager(
mojom::FrameSinkManagerParamsPtr params) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VizCompositorThreadRunnerImpl::
CreateFrameSinkManagerOnCompositorThread,
base::Unretained(this), std::move(params),
nullptr, nullptr));
}
void VizCompositorThreadRunnerImpl::CreateFrameSinkManager(
mojom::FrameSinkManagerParamsPtr params,
gpu::CommandBufferTaskExecutor* task_executor,
GpuServiceImpl* gpu_service) {
// All of the unretained objects are owned on the GPU thread and destroyed
// after VizCompositorThread has been shutdown.
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VizCompositorThreadRunnerImpl::
CreateFrameSinkManagerOnCompositorThread,
base::Unretained(this), std::move(params),
base::Unretained(task_executor),
base::Unretained(gpu_service)));
}
void VizCompositorThreadRunnerImpl::CreateFrameSinkManagerOnCompositorThread(
mojom::FrameSinkManagerParamsPtr params,
gpu::CommandBufferTaskExecutor* task_executor,
GpuServiceImpl* gpu_service) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!frame_sink_manager_);
if (features::IsUsingSkiaRenderer())
gpu::SchedulerSequence::DefaultDisallowScheduleTaskOnCurrentThread();
server_shared_bitmap_manager_ = std::make_unique<ServerSharedBitmapManager>();
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
server_shared_bitmap_manager_.get(), "ServerSharedBitmapManager",
task_runner_);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
const bool headless = command_line->HasSwitch(switches::kHeadless);
const bool run_all_compositor_stages_before_draw =
command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw);
if (task_executor) {
DCHECK(gpu_service);
// Create OutputSurfaceProvider usable for GPU + software compositing.
gpu_memory_buffer_manager_ =
std::make_unique<InProcessGpuMemoryBufferManager>(
gpu_service->gpu_memory_buffer_factory(),
gpu_service->sync_point_manager());
auto* image_factory = gpu_service->gpu_image_factory();
output_surface_provider_ = std::make_unique<OutputSurfaceProviderImpl>(
gpu_service, task_executor, gpu_service,
gpu_memory_buffer_manager_.get(), image_factory, headless);
// Create video frame pool context provider that will enable the frame sink
// manager to create GMB-backed video frames.
gmb_video_frame_pool_context_provider_ =
std::make_unique<GmbVideoFramePoolContextProviderImpl>(
gpu_service, gpu_memory_buffer_manager_.get());
} else {
// Create OutputSurfaceProvider usable for software compositing only.
output_surface_provider_ =
std::make_unique<OutputSurfaceProviderImpl>(headless);
}
// Create FrameSinkManagerImpl.
FrameSinkManagerImpl::InitParams init_params;
init_params.shared_bitmap_manager = server_shared_bitmap_manager_.get();
// Set default activation deadline to infinite if client doesn't provide one.
init_params.activation_deadline_in_frames = absl::nullopt;
if (params->use_activation_deadline) {
init_params.activation_deadline_in_frames =
params->activation_deadline_in_frames;
}
init_params.output_surface_provider = output_surface_provider_.get();
init_params.gmb_context_provider =
gmb_video_frame_pool_context_provider_.get();
init_params.restart_id = params->restart_id;
init_params.run_all_compositor_stages_before_draw =
run_all_compositor_stages_before_draw;
init_params.log_capture_pipeline_in_webrtc =
features::ShouldWebRtcLogCapturePipeline();
init_params.debug_renderer_settings = params->debug_renderer_settings;
if (gpu_service)
init_params.host_process_id = gpu_service->host_process_id();
init_params.hint_session_factory = hint_session_factory_.get();
frame_sink_manager_ = std::make_unique<FrameSinkManagerImpl>(init_params);
frame_sink_manager_->BindAndSetClient(
std::move(params->frame_sink_manager), nullptr,
std::move(params->frame_sink_manager_client));
}
void VizCompositorThreadRunnerImpl::TearDownOnCompositorThread() {
DCHECK(task_runner_->BelongsToCurrentThread());
weak_factory_.InvalidateWeakPtrs();
if (server_shared_bitmap_manager_) {
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
server_shared_bitmap_manager_.get());
}
frame_sink_manager_.reset();
hint_session_factory_.reset();
output_surface_provider_.reset();
gpu_memory_buffer_manager_.reset();
server_shared_bitmap_manager_.reset();
}
} // namespace viz