| Index: components/mus/common/gpu_service.cc
|
| diff --git a/components/mus/common/gpu_service.cc b/components/mus/common/gpu_service.cc
|
| index c3b15ff7cbf367a08a042f556ee07bd6f3771316..4eea3e45972eef52d0efb41548cab1860adbe77f 100644
|
| --- a/components/mus/common/gpu_service.cc
|
| +++ b/components/mus/common/gpu_service.cc
|
| @@ -9,7 +9,6 @@
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "build/build_config.h"
|
| #include "components/mus/common/gpu_type_converters.h"
|
| -#include "components/mus/common/mojo_gpu_memory_buffer_manager.h"
|
| #include "components/mus/common/switches.h"
|
| #include "components/mus/public/interfaces/gpu_service.mojom.h"
|
| #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
|
| @@ -18,18 +17,38 @@
|
|
|
| namespace mus {
|
|
|
| -GpuService::GpuService()
|
| +namespace {
|
| +
|
| +void PostTask(scoped_refptr<base::SingleThreadTaskRunner> runner,
|
| + const tracked_objects::Location& from_here,
|
| + const base::Closure& callback) {
|
| + runner->PostTask(from_here, callback);
|
| +}
|
| +
|
| +GpuService* g_gpu_service = nullptr;
|
| +}
|
| +
|
| +GpuService::GpuService(shell::Connector* connector)
|
| : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + connector_(connector),
|
| shutdown_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
| base::WaitableEvent::InitialState::NOT_SIGNALED),
|
| io_thread_("GPUIOThread"),
|
| - gpu_memory_buffer_manager_(new MojoGpuMemoryBufferManager) {
|
| + gpu_memory_buffer_manager_(new MojoGpuMemoryBufferManager),
|
| + is_establishing_(false),
|
| + establishing_condition_(&lock_) {
|
| + DCHECK(main_task_runner_);
|
| + DCHECK(connector_);
|
| base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
|
| thread_options.priority = base::ThreadPriority::NORMAL;
|
| CHECK(io_thread_.StartWithOptions(thread_options));
|
| }
|
|
|
| -GpuService::~GpuService() {}
|
| +GpuService::~GpuService() {
|
| + DCHECK(IsMainThread());
|
| + if (gpu_channel_)
|
| + gpu_channel_->DestroyChannel();
|
| +}
|
|
|
| // static
|
| bool GpuService::UseChromeGpuCommandBuffer() {
|
| @@ -44,45 +63,166 @@ bool GpuService::UseChromeGpuCommandBuffer() {
|
| }
|
|
|
| // static
|
| +void GpuService::Initialize(shell::Connector* connector) {
|
| + DCHECK(!g_gpu_service);
|
| + g_gpu_service = new GpuService(connector);
|
| +}
|
| +
|
| +// static
|
| +void GpuService::Terminate() {
|
| + DCHECK(g_gpu_service);
|
| + delete g_gpu_service;
|
| + g_gpu_service = nullptr;
|
| +}
|
| +
|
| +// static
|
| GpuService* GpuService::GetInstance() {
|
| - return base::Singleton<GpuService,
|
| - base::LeakySingletonTraits<GpuService>>::get();
|
| + DCHECK(g_gpu_service);
|
| + return g_gpu_service;
|
| +}
|
| +
|
| +void GpuService::EstablishGpuChannel(const base::Closure& callback) {
|
| + base::AutoLock auto_lock(lock_);
|
| + auto runner = base::ThreadTaskRunnerHandle::Get();
|
| + if (GetGpuChannelLocked()) {
|
| + runner->PostTask(FROM_HERE, callback);
|
| + return;
|
| + }
|
| +
|
| + base::Closure wrapper_callback =
|
| + IsMainThread() ? callback
|
| + : base::Bind(PostTask, runner, FROM_HERE, callback);
|
| + establish_callbacks_.push_back(wrapper_callback);
|
| +
|
| + if (!is_establishing_) {
|
| + is_establishing_ = true;
|
| + main_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&GpuService::EstablishGpuChannelOnMainThread,
|
| + base::Unretained(this)));
|
| + }
|
| }
|
|
|
| -scoped_refptr<gpu::GpuChannelHost> GpuService::EstablishGpuChannel(
|
| - shell::Connector* connector) {
|
| +scoped_refptr<gpu::GpuChannelHost> GpuService::EstablishGpuChannelSync() {
|
| base::AutoLock auto_lock(lock_);
|
| + if (GetGpuChannelLocked())
|
| + return gpu_channel_;
|
| +
|
| + if (IsMainThread()) {
|
| + is_establishing_ = true;
|
| + EstablishGpuChannelOnMainThreadSyncLocked();
|
| + } else {
|
| + if (!is_establishing_) {
|
| + // Create an establishing gpu channel task, if there isn't one.
|
| + is_establishing_ = true;
|
| + main_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&GpuService::EstablishGpuChannelOnMainThread,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + // Wait until the pending establishing task is finished.
|
| + do {
|
| + establishing_condition_.Wait();
|
| + } while (is_establishing_);
|
| + }
|
| + return gpu_channel_;
|
| +}
|
| +
|
| +scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannel() {
|
| + base::AutoLock auto_lock(lock_);
|
| + return GetGpuChannelLocked();
|
| +}
|
| +
|
| +scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannelLocked() {
|
| if (gpu_channel_ && gpu_channel_->IsLost()) {
|
| - gpu_channel_->DestroyChannel();
|
| + main_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&gpu::GpuChannelHost::DestroyChannel, gpu_channel_));
|
| gpu_channel_ = nullptr;
|
| }
|
| + return gpu_channel_;
|
| +}
|
|
|
| - if (gpu_channel_)
|
| - return gpu_channel_;
|
| +void GpuService::EstablishGpuChannelOnMainThread() {
|
| + base::AutoLock auto_lock(lock_);
|
| + DCHECK(IsMainThread());
|
| +
|
| + // In GpuService::EstablishGpuChannelOnMainThreadSyncLocked(), we use the sync
|
| + // mojo EstablishGpuChannel call, after that call the gpu_service_ will be
|
| + // reset immediatelly. So gpu_service_ should be always null here.
|
| + DCHECK(!gpu_service_);
|
| +
|
| + // is_establishing_ is false, it means GpuService::EstablishGpuChannelSync()
|
| + // has been used, and we don't need try to establish a new GPU channel
|
| + // anymore.
|
| + if (!is_establishing_)
|
| + return;
|
| +
|
| + connector_->ConnectToInterface("mojo:mus", &gpu_service_);
|
| + const bool locked = false;
|
| + gpu_service_->EstablishGpuChannel(
|
| + base::Bind(&GpuService::EstablishGpuChannelOnMainThreadDone,
|
| + base::Unretained(this), locked));
|
| +}
|
| +
|
| +void GpuService::EstablishGpuChannelOnMainThreadSyncLocked() {
|
| + DCHECK(IsMainThread());
|
| + DCHECK(is_establishing_);
|
|
|
| - mus::mojom::GpuServicePtr gpu_service;
|
| - connector->ConnectToInterface("mojo:mus", &gpu_service);
|
| + // In browser process, EstablishGpuChannelSync() is only used by testing &
|
| + // GpuProcessTransportFactory::GetGLHelper(). For GetGLHelper(), it expects
|
| + // the gpu channel has been established, so it should not reach here.
|
| + // For testing, the asyc method should not be used.
|
| + // In renderer process, we only use EstablishGpuChannelSync().
|
| + // So the gpu_service_ should be null here.
|
| + DCHECK(!gpu_service_);
|
|
|
| int client_id = 0;
|
| mojom::ChannelHandlePtr channel_handle;
|
| mojom::GpuInfoPtr gpu_info;
|
| + connector_->ConnectToInterface("mojo:mus", &gpu_service_);
|
| {
|
| - // TODO(penghuang): Remove the ScopedAllowSyncCall when HW rendering is
|
| - // enabled in mus chrome.
|
| + base::AutoUnlock auto_unlock(lock_);
|
| mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call;
|
| - if (!gpu_service->EstablishGpuChannel(&client_id, &channel_handle,
|
| - &gpu_info)) {
|
| + if (!gpu_service_->EstablishGpuChannel(&client_id, &channel_handle,
|
| + &gpu_info)) {
|
| DLOG(WARNING)
|
| << "Channel encountered error while establishing gpu channel.";
|
| - return nullptr;
|
| + return;
|
| }
|
| }
|
| + const bool locked = true;
|
| + EstablishGpuChannelOnMainThreadDone(
|
| + locked, client_id, std::move(channel_handle), std::move(gpu_info));
|
| +}
|
|
|
| - // TODO(penghuang): Get the real gpu info from mus.
|
| - gpu_channel_ = gpu::GpuChannelHost::Create(
|
| - this, client_id, gpu::GPUInfo(), channel_handle.To<IPC::ChannelHandle>(),
|
| - &shutdown_event_, gpu_memory_buffer_manager_.get());
|
| - return gpu_channel_;
|
| +void GpuService::EstablishGpuChannelOnMainThreadDone(
|
| + bool locked,
|
| + int client_id,
|
| + mojom::ChannelHandlePtr channel_handle,
|
| + mojom::GpuInfoPtr gpu_info) {
|
| + DCHECK(IsMainThread());
|
| + scoped_refptr<gpu::GpuChannelHost> gpu_channel;
|
| + if (client_id) {
|
| + // TODO(penghuang): Get the real gpu info from mus.
|
| + gpu_channel = gpu::GpuChannelHost::Create(
|
| + this, client_id, gpu::GPUInfo(),
|
| + channel_handle.To<IPC::ChannelHandle>(), &shutdown_event_,
|
| + gpu_memory_buffer_manager_.get());
|
| + }
|
| +
|
| + auto auto_lock = base::WrapUnique<base::AutoLock>(
|
| + locked ? nullptr : new base::AutoLock(lock_));
|
| + DCHECK(is_establishing_);
|
| + DCHECK(!gpu_channel_);
|
| +
|
| + is_establishing_ = false;
|
| + gpu_channel_ = gpu_channel;
|
| + establishing_condition_.Broadcast();
|
| +
|
| + for (const auto& i : establish_callbacks_)
|
| + i.Run();
|
| + establish_callbacks_.clear();
|
| + gpu_service_.reset();
|
| }
|
|
|
| bool GpuService::IsMainThread() {
|
|
|