Skip to content

Commit efb339f

Browse files
author
Emmanuel Garcia
authored
Only clear GL context after changing the thread configuration (flutter#20965)
1 parent 5a2db33 commit efb339f

File tree

4 files changed

+82
-12
lines changed

4 files changed

+82
-12
lines changed

fml/raster_thread_merger.cc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ RasterThreadMerger::RasterThreadMerger(fml::TaskQueueId platform_queue_id,
2121
FML_CHECK(!task_queues_->Owns(platform_queue_id_, gpu_queue_id_));
2222
}
2323

24+
void RasterThreadMerger::SetMergeUnmergeCallback(const fml::closure& callback) {
25+
merge_unmerge_callback_ = callback;
26+
}
27+
2428
void RasterThreadMerger::MergeWithLease(size_t lease_term) {
2529
std::scoped_lock lock(lease_term_mutex_);
2630
if (TaskQueuesAreSame()) {
@@ -30,11 +34,19 @@ void RasterThreadMerger::MergeWithLease(size_t lease_term) {
3034
return;
3135
}
3236
FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
33-
if (!IsMergedUnSafe()) {
34-
bool success = task_queues_->Merge(platform_queue_id_, gpu_queue_id_);
35-
FML_CHECK(success) << "Unable to merge the raster and platform threads.";
36-
lease_term_ = lease_term;
37+
38+
if (IsMergedUnSafe()) {
39+
merged_condition_.notify_one();
40+
return;
41+
}
42+
43+
bool success = task_queues_->Merge(platform_queue_id_, gpu_queue_id_);
44+
if (success && merge_unmerge_callback_ != nullptr) {
45+
merge_unmerge_callback_();
3746
}
47+
FML_CHECK(success) << "Unable to merge the raster and platform threads.";
48+
lease_term_ = lease_term;
49+
3850
merged_condition_.notify_one();
3951
}
4052

@@ -48,6 +60,9 @@ void RasterThreadMerger::UnMergeNow() {
4860
}
4961
lease_term_ = 0;
5062
bool success = task_queues_->Unmerge(platform_queue_id_);
63+
if (success && merge_unmerge_callback_ != nullptr) {
64+
merge_unmerge_callback_();
65+
}
5166
FML_CHECK(success) << "Unable to un-merge the raster and platform threads.";
5267
}
5368

fml/raster_thread_merger.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ class RasterThreadMerger
8585
// noop.
8686
bool IsEnabled();
8787

88+
// Registers a callback that can be used to clean up global state right after
89+
// the thread configuration has changed.
90+
//
91+
// For example, it can be used to clear the GL context so it can be used in
92+
// the next task from a different thread.
93+
void SetMergeUnmergeCallback(const fml::closure& callback);
94+
8895
private:
8996
static const int kLeaseNotSet;
9097
fml::TaskQueueId platform_queue_id_;
@@ -93,6 +100,7 @@ class RasterThreadMerger
93100
std::atomic_int lease_term_;
94101
std::condition_variable merged_condition_;
95102
std::mutex lease_term_mutex_;
103+
fml::closure merge_unmerge_callback_;
96104
bool enabled_;
97105

98106
bool IsMergedUnSafe() const;

fml/raster_thread_merger_unittests.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,5 +579,53 @@ TEST(RasterThreadMerger, RunExpiredTasksWhileFirstTaskUnMergesThreads) {
579579
thread_raster.join();
580580
}
581581

582+
TEST(RasterThreadMerger, SetMergeUnmergeCallback) {
583+
fml::MessageLoop* loop1 = nullptr;
584+
fml::AutoResetWaitableEvent latch1;
585+
fml::AutoResetWaitableEvent term1;
586+
std::thread thread1([&loop1, &latch1, &term1]() {
587+
fml::MessageLoop::EnsureInitializedForCurrentThread();
588+
loop1 = &fml::MessageLoop::GetCurrent();
589+
latch1.Signal();
590+
term1.Wait();
591+
});
592+
593+
fml::MessageLoop* loop2 = nullptr;
594+
fml::AutoResetWaitableEvent latch2;
595+
fml::AutoResetWaitableEvent term2;
596+
std::thread thread2([&loop2, &latch2, &term2]() {
597+
fml::MessageLoop::EnsureInitializedForCurrentThread();
598+
loop2 = &fml::MessageLoop::GetCurrent();
599+
latch2.Signal();
600+
term2.Wait();
601+
});
602+
603+
latch1.Wait();
604+
latch2.Wait();
605+
606+
fml::TaskQueueId qid1 = loop1->GetTaskRunner()->GetTaskQueueId();
607+
fml::TaskQueueId qid2 = loop2->GetTaskRunner()->GetTaskQueueId();
608+
609+
const auto raster_thread_merger =
610+
fml::MakeRefCounted<fml::RasterThreadMerger>(qid1, qid2);
611+
612+
int callbacks = 0;
613+
raster_thread_merger->SetMergeUnmergeCallback(
614+
[&callbacks]() { callbacks++; });
615+
616+
ASSERT_EQ(0, callbacks);
617+
618+
raster_thread_merger->MergeWithLease(1);
619+
ASSERT_EQ(1, callbacks);
620+
621+
raster_thread_merger->DecrementLease();
622+
ASSERT_EQ(2, callbacks);
623+
624+
term1.Signal();
625+
term2.Signal();
626+
thread1.join();
627+
thread2.join();
628+
}
629+
582630
} // namespace testing
583631
} // namespace fml

shell/common/rasterizer.cc

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ void Rasterizer::Setup(std::unique_ptr<Surface> surface) {
8989
delegate_.GetTaskRunners().GetRasterTaskRunner()->GetTaskQueueId();
9090
raster_thread_merger_ =
9191
fml::MakeRefCounted<fml::RasterThreadMerger>(platform_id, gpu_id);
92+
raster_thread_merger_->SetMergeUnmergeCallback([=]() {
93+
// Clear the GL context after the thread configuration has changed.
94+
if (surface_) {
95+
surface_->ClearRenderContext();
96+
}
97+
});
9298
}
9399
#endif
94100
}
@@ -102,6 +108,7 @@ void Rasterizer::Teardown() {
102108
raster_thread_merger_.get()->IsMerged()) {
103109
FML_DCHECK(raster_thread_merger_->IsEnabled());
104110
raster_thread_merger_->UnMergeNow();
111+
raster_thread_merger_->SetMergeUnmergeCallback(nullptr);
105112
}
106113
}
107114

@@ -467,14 +474,6 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) {
467474

468475
FireNextFrameCallbackIfPresent();
469476

470-
// Clear the render context after submitting the frame.
471-
// This ensures that the GL context is released after drawing to the
472-
// surface.
473-
//
474-
// The GL context must be clear before performing Gr context deferred
475-
// cleanup.
476-
surface_->ClearRenderContext();
477-
478477
if (surface_->GetContext()) {
479478
TRACE_EVENT0("flutter", "PerformDeferredSkiaCleanup");
480479
surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration);

0 commit comments

Comments
 (0)