1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define FML_USED_ON_EMBEDDER
6
7#include "flutter/fml/raster_thread_merger.h"
8
9#include <utility>
10
11#include "flutter/fml/message_loop_impl.h"
12
13namespace fml {
14
15RasterThreadMerger::RasterThreadMerger(fml::TaskQueueId platform_queue_id,
16 fml::TaskQueueId gpu_queue_id)
17 : RasterThreadMerger(
18 MakeRefCounted<SharedThreadMerger>(args&: platform_queue_id, args&: gpu_queue_id),
19 platform_queue_id,
20 gpu_queue_id) {}
21
22RasterThreadMerger::RasterThreadMerger(
23 fml::RefPtr<fml::SharedThreadMerger> shared_merger,
24 fml::TaskQueueId platform_queue_id,
25 fml::TaskQueueId gpu_queue_id)
26 : platform_queue_id_(platform_queue_id),
27 gpu_queue_id_(gpu_queue_id),
28 shared_merger_(std::move(shared_merger)) {}
29
30void RasterThreadMerger::SetMergeUnmergeCallback(const fml::closure& callback) {
31 merge_unmerge_callback_ = callback;
32}
33
34const fml::RefPtr<fml::SharedThreadMerger>&
35RasterThreadMerger::GetSharedRasterThreadMerger() const {
36 return shared_merger_;
37}
38
39fml::RefPtr<fml::RasterThreadMerger>
40RasterThreadMerger::CreateOrShareThreadMerger(
41 const fml::RefPtr<fml::RasterThreadMerger>& parent_merger,
42 TaskQueueId platform_id,
43 TaskQueueId raster_id) {
44 if (parent_merger && parent_merger->platform_queue_id_ == platform_id &&
45 parent_merger->gpu_queue_id_ == raster_id) {
46 auto shared_merger = parent_merger->GetSharedRasterThreadMerger();
47 return fml::MakeRefCounted<RasterThreadMerger>(args&: shared_merger, args&: platform_id,
48 args&: raster_id);
49 } else {
50 return fml::MakeRefCounted<RasterThreadMerger>(args&: platform_id, args&: raster_id);
51 }
52}
53
54void RasterThreadMerger::MergeWithLease(size_t lease_term) {
55 std::scoped_lock lock(mutex_);
56 if (TaskQueuesAreSame()) {
57 return;
58 }
59 if (!IsEnabledUnSafe()) {
60 return;
61 }
62 FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
63
64 if (IsMergedUnSafe()) {
65 merged_condition_.notify_one();
66 return;
67 }
68
69 bool success = shared_merger_->MergeWithLease(caller: this, lease_term);
70 if (success && merge_unmerge_callback_ != nullptr) {
71 merge_unmerge_callback_();
72 }
73
74 merged_condition_.notify_one();
75}
76
77void RasterThreadMerger::UnMergeNowIfLastOne() {
78 std::scoped_lock lock(mutex_);
79
80 if (TaskQueuesAreSame()) {
81 return;
82 }
83 if (!IsEnabledUnSafe()) {
84 return;
85 }
86 bool success = shared_merger_->UnMergeNowIfLastOne(caller: this);
87 if (success && merge_unmerge_callback_ != nullptr) {
88 merge_unmerge_callback_();
89 }
90}
91
92bool RasterThreadMerger::IsOnPlatformThread() const {
93 return MessageLoop::GetCurrentTaskQueueId() == platform_queue_id_;
94}
95
96bool RasterThreadMerger::IsOnRasterizingThread() {
97 std::scoped_lock lock(mutex_);
98
99 if (IsMergedUnSafe()) {
100 return IsOnPlatformThread();
101 } else {
102 return !IsOnPlatformThread();
103 }
104}
105
106void RasterThreadMerger::ExtendLeaseTo(size_t lease_term) {
107 FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
108 if (TaskQueuesAreSame()) {
109 return;
110 }
111 std::scoped_lock lock(mutex_);
112 if (!IsEnabledUnSafe()) {
113 return;
114 }
115 shared_merger_->ExtendLeaseTo(caller: this, lease_term);
116}
117
118bool RasterThreadMerger::IsMerged() {
119 std::scoped_lock lock(mutex_);
120 return IsMergedUnSafe();
121}
122
123void RasterThreadMerger::Enable() {
124 std::scoped_lock lock(mutex_);
125 shared_merger_->SetEnabledUnSafe(true);
126}
127
128void RasterThreadMerger::Disable() {
129 std::scoped_lock lock(mutex_);
130 shared_merger_->SetEnabledUnSafe(false);
131}
132
133bool RasterThreadMerger::IsEnabled() {
134 std::scoped_lock lock(mutex_);
135 return IsEnabledUnSafe();
136}
137
138bool RasterThreadMerger::IsEnabledUnSafe() const {
139 return shared_merger_->IsEnabledUnSafe();
140}
141
142bool RasterThreadMerger::IsMergedUnSafe() const {
143 return TaskQueuesAreSame() || shared_merger_->IsMergedUnSafe();
144}
145
146bool RasterThreadMerger::TaskQueuesAreSame() const {
147 return platform_queue_id_ == gpu_queue_id_;
148}
149
150void RasterThreadMerger::WaitUntilMerged() {
151 if (TaskQueuesAreSame()) {
152 return;
153 }
154 FML_CHECK(IsOnPlatformThread());
155 std::unique_lock<std::mutex> lock(mutex_);
156 merged_condition_.wait(lk&: lock, pred: [&] { return IsMergedUnSafe(); });
157}
158
159RasterThreadStatus RasterThreadMerger::DecrementLease() {
160 if (TaskQueuesAreSame()) {
161 return RasterThreadStatus::kRemainsMerged;
162 }
163 std::scoped_lock lock(mutex_);
164 if (!IsMergedUnSafe()) {
165 return RasterThreadStatus::kRemainsUnmerged;
166 }
167 if (!IsEnabledUnSafe()) {
168 return RasterThreadStatus::kRemainsMerged;
169 }
170 bool unmerged_after_decrement = shared_merger_->DecrementLease(caller: this);
171 if (unmerged_after_decrement) {
172 if (merge_unmerge_callback_ != nullptr) {
173 merge_unmerge_callback_();
174 }
175 return RasterThreadStatus::kUnmergedNow;
176 }
177
178 return RasterThreadStatus::kRemainsMerged;
179}
180
181} // namespace fml
182

source code of flutter_engine/flutter/fml/raster_thread_merger.cc