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 #ifndef FLUTTER_FLOW_SKIA_GPU_OBJECT_H_ 6 #define FLUTTER_FLOW_SKIA_GPU_OBJECT_H_ 7 8 #include <mutex> 9 #include <queue> 10 11 #include "flutter/fml/memory/ref_counted.h" 12 #include "flutter/fml/memory/weak_ptr.h" 13 #include "flutter/fml/task_runner.h" 14 #include "third_party/skia/include/core/SkRefCnt.h" 15 16 namespace flutter { 17 18 // A queue that holds Skia objects that must be destructed on the the given task 19 // runner. 20 class SkiaUnrefQueue : public fml::RefCountedThreadSafe<SkiaUnrefQueue> { 21 public: 22 void Unref(SkRefCnt* object); 23 24 // Usually, the drain is called automatically. However, during IO manager 25 // shutdown (when the platform side reference to the OpenGL context is about 26 // to go away), we may need to pre-emptively drain the unref queue. It is the 27 // responsibility of the caller to ensure that no further unrefs are queued 28 // after this call. 29 void Drain(bool finish = false); 30 31 private: 32 const fml::RefPtr<fml::TaskRunner> task_runner_; 33 const fml::TimeDelta drain_delay_; 34 std::mutex mutex_; 35 std::deque<SkRefCnt*> objects_; 36 bool drain_pending_; 37 bool invalid_ = false; 38 39 SkiaUnrefQueue(fml::RefPtr<fml::TaskRunner> task_runner, 40 fml::TimeDelta delay); 41 42 ~SkiaUnrefQueue(); 43 44 FML_FRIEND_REF_COUNTED_THREAD_SAFE(SkiaUnrefQueue); 45 FML_FRIEND_MAKE_REF_COUNTED(SkiaUnrefQueue); 46 FML_DISALLOW_COPY_AND_ASSIGN(SkiaUnrefQueue); 47 }; 48 49 /// An object whose deallocation needs to be performed on an specific unref 50 /// queue. The template argument U need to have a call operator that returns 51 /// that unref queue. 52 template <class T> 53 class SkiaGPUObject { 54 public: 55 using SkiaObjectType = T; 56 57 SkiaGPUObject() = default; 58 SkiaGPUObject(sk_sp<SkiaObjectType> object,fml::RefPtr<SkiaUnrefQueue> queue)59 SkiaGPUObject(sk_sp<SkiaObjectType> object, fml::RefPtr<SkiaUnrefQueue> queue) 60 : object_(std::move(object)), queue_(std::move(queue)) { 61 FML_DCHECK(queue_ && object_); 62 } 63 64 SkiaGPUObject(SkiaGPUObject&&) = default; 65 ~SkiaGPUObject()66 ~SkiaGPUObject() { reset(); } 67 68 SkiaGPUObject& operator=(SkiaGPUObject&&) = default; 69 get()70 sk_sp<SkiaObjectType> get() const { return object_; } 71 reset()72 void reset() { 73 if (object_) { 74 queue_->Unref(object_.release()); 75 } 76 queue_ = nullptr; 77 FML_DCHECK(object_ == nullptr); 78 } 79 80 private: 81 sk_sp<SkiaObjectType> object_; 82 fml::RefPtr<SkiaUnrefQueue> queue_; 83 84 FML_DISALLOW_COPY_AND_ASSIGN(SkiaGPUObject); 85 }; 86 87 } // namespace flutter 88 89 #endif // FLUTTER_FLOW_SKIA_GPU_OBJECT_H_ 90