diff --git a/engine/src/flutter/lib/ui/BUILD.gn b/engine/src/flutter/lib/ui/BUILD.gn index fd02dab359..8c0dbded34 100644 --- a/engine/src/flutter/lib/ui/BUILD.gn +++ b/engine/src/flutter/lib/ui/BUILD.gn @@ -42,6 +42,7 @@ source_set("ui") { "painting/rrect.h", "painting/shader.cc", "painting/shader.h", + "painting/utils.cc", "painting/utils.h", "painting/vertices.cc", "painting/vertices.h", diff --git a/engine/src/flutter/lib/ui/painting/utils.cc b/engine/src/flutter/lib/ui/painting/utils.cc new file mode 100644 index 0000000000..c6ee205fdd --- /dev/null +++ b/engine/src/flutter/lib/ui/painting/utils.cc @@ -0,0 +1,48 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/common/threads.h" +#include "flutter/lib/ui/painting/utils.h" + +namespace blink { + +namespace { + +constexpr ftl::TimeDelta kDrainDelay = ftl::TimeDelta::FromMilliseconds(250); + +} // anonymous namespace + +SkiaUnrefQueue::SkiaUnrefQueue() + : drain_pending_(false) {} + +SkiaUnrefQueue SkiaUnrefQueue::instance_; + +SkiaUnrefQueue& SkiaUnrefQueue::Get() { + return instance_; +} + +void SkiaUnrefQueue::Unref(SkRefCnt* object) { + ftl::MutexLocker lock(&mutex_); + objects_.push_back(object); + if (!drain_pending_) { + drain_pending_ = true; + Threads::IO()->PostDelayedTask([this] { Drain(); }, + kDrainDelay); + } +} + +void SkiaUnrefQueue::Drain() { + std::deque skia_objects; + { + ftl::MutexLocker lock(&mutex_); + objects_.swap(skia_objects); + drain_pending_ = false; + } + + for (SkRefCnt* skia_object : skia_objects) { + skia_object->unref(); + } +} + +} // namespace blink diff --git a/engine/src/flutter/lib/ui/painting/utils.h b/engine/src/flutter/lib/ui/painting/utils.h index ed194ca82c..eedd9f929f 100644 --- a/engine/src/flutter/lib/ui/painting/utils.h +++ b/engine/src/flutter/lib/ui/painting/utils.h @@ -2,15 +2,35 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/common/threads.h" +#include "lib/ftl/synchronization/mutex.h" #include "third_party/skia/include/core/SkRefCnt.h" +#include + namespace blink { +// A queue that holds Skia objects that must be destructed on the IO thread. +class SkiaUnrefQueue { + public: + static SkiaUnrefQueue& Get(); + + void Unref(SkRefCnt* object); + + private: + SkiaUnrefQueue(); + void Drain(); + + static SkiaUnrefQueue instance_; + + ftl::Mutex mutex_; + std::deque objects_ FTL_GUARDED_BY(mutex_); + bool drain_pending_ FTL_GUARDED_BY(mutex_); +}; + template void SkiaUnrefOnIOThread(sk_sp* sp) { T* object = sp->release(); if (object) { - Threads::IO()->PostTask([object]() { object->unref(); }); + SkiaUnrefQueue::Get().Unref(object); } }