blob: 88b33dc1e774ff0760d308f5655a9d5ce5ea4d73 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define FML_USED_ON_EMBEDDER
#include "flutter/fml/raster_thread_merger.h"
#include "flutter/fml/message_loop_impl.h"
namespace fml {
RasterThreadMerger::RasterThreadMerger(fml::TaskQueueId platform_queue_id,
fml::TaskQueueId gpu_queue_id)
: RasterThreadMerger(
MakeRefCounted<SharedThreadMerger>(platform_queue_id, gpu_queue_id),
platform_queue_id,
gpu_queue_id) {}
RasterThreadMerger::RasterThreadMerger(
fml::RefPtr<fml::SharedThreadMerger> shared_merger,
fml::TaskQueueId platform_queue_id,
fml::TaskQueueId gpu_queue_id)
: platform_queue_id_(platform_queue_id),
gpu_queue_id_(gpu_queue_id),
shared_merger_(shared_merger) {}
void RasterThreadMerger::SetMergeUnmergeCallback(const fml::closure& callback) {
merge_unmerge_callback_ = callback;
}
const fml::RefPtr<fml::SharedThreadMerger>&
RasterThreadMerger::GetSharedRasterThreadMerger() const {
return shared_merger_;
}
fml::RefPtr<fml::RasterThreadMerger>
RasterThreadMerger::CreateOrShareThreadMerger(
const fml::RefPtr<fml::RasterThreadMerger>& parent_merger,
TaskQueueId platform_id,
TaskQueueId raster_id) {
if (parent_merger && parent_merger->platform_queue_id_ == platform_id &&
parent_merger->gpu_queue_id_ == raster_id) {
auto shared_merger = parent_merger->GetSharedRasterThreadMerger();
return fml::MakeRefCounted<RasterThreadMerger>(shared_merger, platform_id,
raster_id);
} else {
return fml::MakeRefCounted<RasterThreadMerger>(platform_id, raster_id);
}
}
void RasterThreadMerger::MergeWithLease(size_t lease_term) {
std::scoped_lock lock(mutex_);
if (TaskQueuesAreSame()) {
return;
}
if (!IsEnabledUnSafe()) {
return;
}
FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
if (IsMergedUnSafe()) {
merged_condition_.notify_one();
return;
}
bool success = shared_merger_->MergeWithLease(this, lease_term);
if (success && merge_unmerge_callback_ != nullptr) {
merge_unmerge_callback_();
}
merged_condition_.notify_one();
}
void RasterThreadMerger::UnMergeNowIfLastOne() {
std::scoped_lock lock(mutex_);
if (TaskQueuesAreSame()) {
return;
}
if (!IsEnabledUnSafe()) {
return;
}
bool success = shared_merger_->UnMergeNowIfLastOne(this);
if (success && merge_unmerge_callback_ != nullptr) {
merge_unmerge_callback_();
}
}
bool RasterThreadMerger::IsOnPlatformThread() const {
return MessageLoop::GetCurrentTaskQueueId() == platform_queue_id_;
}
bool RasterThreadMerger::IsOnRasterizingThread() {
std::scoped_lock lock(mutex_);
if (IsMergedUnSafe()) {
return IsOnPlatformThread();
} else {
return !IsOnPlatformThread();
}
}
void RasterThreadMerger::ExtendLeaseTo(size_t lease_term) {
FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
if (TaskQueuesAreSame()) {
return;
}
std::scoped_lock lock(mutex_);
if (!IsEnabledUnSafe()) {
return;
}
shared_merger_->ExtendLeaseTo(this, lease_term);
}
bool RasterThreadMerger::IsMerged() {
std::scoped_lock lock(mutex_);
return IsMergedUnSafe();
}
void RasterThreadMerger::Enable() {
std::scoped_lock lock(mutex_);
shared_merger_->SetEnabledUnSafe(true);
}
void RasterThreadMerger::Disable() {
std::scoped_lock lock(mutex_);
shared_merger_->SetEnabledUnSafe(false);
}
bool RasterThreadMerger::IsEnabled() {
std::scoped_lock lock(mutex_);
return IsEnabledUnSafe();
}
bool RasterThreadMerger::IsEnabledUnSafe() const {
return shared_merger_->IsEnabledUnSafe();
}
bool RasterThreadMerger::IsMergedUnSafe() const {
return TaskQueuesAreSame() || shared_merger_->IsMergedUnSafe();
}
bool RasterThreadMerger::TaskQueuesAreSame() const {
return platform_queue_id_ == gpu_queue_id_;
}
void RasterThreadMerger::WaitUntilMerged() {
if (TaskQueuesAreSame()) {
return;
}
FML_CHECK(IsOnPlatformThread());
std::unique_lock<std::mutex> lock(mutex_);
merged_condition_.wait(lock, [&] { return IsMergedUnSafe(); });
}
RasterThreadStatus RasterThreadMerger::DecrementLease() {
if (TaskQueuesAreSame()) {
return RasterThreadStatus::kRemainsMerged;
}
std::scoped_lock lock(mutex_);
if (!IsMergedUnSafe()) {
return RasterThreadStatus::kRemainsUnmerged;
}
if (!IsEnabledUnSafe()) {
return RasterThreadStatus::kRemainsMerged;
}
bool unmerged_after_decrement = shared_merger_->DecrementLease(this);
if (unmerged_after_decrement) {
if (merge_unmerge_callback_ != nullptr) {
merge_unmerge_callback_();
}
return RasterThreadStatus::kUnmergedNow;
}
return RasterThreadStatus::kRemainsMerged;
}
} // namespace fml