1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
// Copyright 2024 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/frame_sinks/shared_image_interface_provider.h"
#include <memory>
#include "base/functional/callback.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "gpu/command_buffer/service/scheduler_sequence.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image_interface_in_process.h"
namespace viz {
SharedImageInterfaceProvider::SharedImageInterfaceProvider(
GpuServiceImpl* gpu_service)
: gpu_service_(gpu_service) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
}
SharedImageInterfaceProvider::~SharedImageInterfaceProvider() {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
base::AutoLock hold(context_lock_);
if (shared_context_state_) {
shared_context_state_->RemoveContextLostObserver(this);
shared_context_state_.reset();
}
}
gpu::SharedImageInterface*
SharedImageInterfaceProvider::GetSharedImageInterface() {
if (NeedsNewSharedImageInterface()) {
CreateSharedImageInterface();
}
return shared_image_interface_.get();
}
bool SharedImageInterfaceProvider::NeedsNewSharedImageInterface() {
base::AutoLock hold(context_lock_);
return !shared_image_interface_ || context_lost_;
}
void SharedImageInterfaceProvider::CreateSharedImageInterface() {
// This function should only be called on the compositor thread.
CHECK(!gpu_service_->main_runner()->BelongsToCurrentThread());
if (!scheduler_sequence_) {
// TODO(vmpstr): This can use compositor_gpu_task_runner instead. However,
// we also then need to create a SharedContextState from the same runner.
// That checks that the access is happening from the thread that owns the
// runner, which would not be the case here. All of this, however, is an
// optimization and for now we can use main runner for these textures.
scheduler_sequence_ = std::make_unique<gpu::SchedulerSequence>(
gpu_service_->GetGpuScheduler(), gpu_service_->main_runner(),
/*target_thread_is_always_available=*/true);
}
base::ScopedAllowBaseSyncPrimitives allow_wait;
base::WaitableEvent event;
scheduler_sequence_->ScheduleTask(
base::BindOnce(
&SharedImageInterfaceProvider::CreateSharedImageInterfaceOnGpu,
base::Unretained(this), &event),
/*sync_token_fences=*/{}, gpu::SyncToken());
event.Wait();
}
void SharedImageInterfaceProvider::CreateSharedImageInterfaceOnGpu(
base::WaitableEvent* event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
base::AutoLock hold(context_lock_);
shared_context_state_ =
gl::GetGLImplementation() != gl::kGLImplementationDisabled && gpu_service_
? gpu_service_->GetContextState()
: nullptr;
context_lost_ = false;
shared_image_interface_ =
base::MakeRefCounted<gpu::SharedImageInterfaceInProcess>(
scheduler_sequence_.get(), gpu_service_->gpu_preferences(),
gpu_service_->gpu_driver_bug_workarounds(),
gpu_service_->gpu_feature_info(), shared_context_state_.get(),
gpu_service_->shared_image_manager(),
/*is_for_diplay_compositor=*/false,
gpu::SharedImageInterfaceInProcess::OwnerThread::kGpu);
if (shared_context_state_) {
shared_context_state_->AddContextLostObserver(this);
}
event->Signal();
}
void SharedImageInterfaceProvider::OnContextLost() {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
base::AutoLock hold(context_lock_);
shared_context_state_->RemoveContextLostObserver(this);
shared_context_state_ = nullptr;
context_lost_ = true;
}
} // namespace viz
|