| // 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 |