Flutter Engine
skia_gpu_object_unittests.cc
Go to the documentation of this file.
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 #include "flutter/flow/skia_gpu_object.h"
6 
7 #include <future>
8 
9 #include "flutter/fml/message_loop.h"
10 #include "flutter/fml/synchronization/waitable_event.h"
11 #include "flutter/fml/task_runner.h"
12 #include "flutter/testing/thread_test.h"
13 #include "gtest/gtest.h"
14 #include "third_party/skia/include/core/SkRefCnt.h"
15 
16 namespace flutter {
17 namespace testing {
18 
19 class TestSkObject : public SkRefCnt {
20  public:
21  TestSkObject(std::shared_ptr<fml::AutoResetWaitableEvent> latch,
22  fml::TaskQueueId* dtor_task_queue_id)
23  : latch_(latch), dtor_task_queue_id_(dtor_task_queue_id) {}
24 
26  if (dtor_task_queue_id_) {
27  *dtor_task_queue_id_ = fml::MessageLoop::GetCurrentTaskQueueId();
28  }
29  latch_->Signal();
30  }
31 
32  private:
33  std::shared_ptr<fml::AutoResetWaitableEvent> latch_;
34  fml::TaskQueueId* dtor_task_queue_id_;
35 };
36 
37 class SkiaGpuObjectTest : public ThreadTest {
38  public:
40  : unref_task_runner_(CreateNewThread()),
41  unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
42  unref_task_runner(),
43  fml::TimeDelta::FromSeconds(0))),
44  delayed_unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
45  unref_task_runner(),
46  fml::TimeDelta::FromSeconds(3))) {
47  // The unref queues must be created in the same thread of the
48  // unref_task_runner so the queue can access the same-thread-only WeakPtr of
49  // the GrContext constructed during the creation.
50  std::promise<bool> queuesCreated;
51  unref_task_runner_->PostTask([this, &queuesCreated]() {
52  unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
53  unref_task_runner(), fml::TimeDelta::FromSeconds(0));
54  delayed_unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
55  unref_task_runner(), fml::TimeDelta::FromSeconds(3));
56  queuesCreated.set_value(true);
57  });
58  queuesCreated.get_future().wait();
59  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
60  }
61 
63  return unref_task_runner_;
64  }
65  fml::RefPtr<SkiaUnrefQueue> unref_queue() { return unref_queue_; }
67  return delayed_unref_queue_;
68  }
69 
70  private:
71  fml::RefPtr<fml::TaskRunner> unref_task_runner_;
72  fml::RefPtr<SkiaUnrefQueue> unref_queue_;
73  fml::RefPtr<SkiaUnrefQueue> delayed_unref_queue_;
74 };
75 
76 TEST_F(SkiaGpuObjectTest, QueueSimple) {
77  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
78  std::make_shared<fml::AutoResetWaitableEvent>();
79  fml::TaskQueueId dtor_task_queue_id(0);
80  SkRefCnt* ref_object = new TestSkObject(latch, &dtor_task_queue_id);
81 
82  unref_queue()->Unref(ref_object);
83  latch->Wait();
84  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
85 }
86 
87 TEST_F(SkiaGpuObjectTest, ObjectDestructor) {
88  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
89  std::make_shared<fml::AutoResetWaitableEvent>();
90  fml::TaskQueueId dtor_task_queue_id(0);
91  auto object = sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id);
92  {
93  SkiaGPUObject<TestSkObject> sk_object(std::move(object), unref_queue());
94  // Verify that the default SkiaGPUObject dtor queues and unref.
95  }
96 
97  latch->Wait();
98  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
99 }
100 
101 TEST_F(SkiaGpuObjectTest, ObjectReset) {
102  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
103  std::make_shared<fml::AutoResetWaitableEvent>();
104  fml::TaskQueueId dtor_task_queue_id(0);
105  SkiaGPUObject<TestSkObject> sk_object(
106  sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
107  // Verify that explicitly resetting the GPU object queues and unref.
108  sk_object.reset();
109  ASSERT_EQ(sk_object.get(), nullptr);
110  latch->Wait();
111  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
112 }
113 
114 TEST_F(SkiaGpuObjectTest, ObjectResetTwice) {
115  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
116  std::make_shared<fml::AutoResetWaitableEvent>();
117  fml::TaskQueueId dtor_task_queue_id(0);
118  SkiaGPUObject<TestSkObject> sk_object(
119  sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
120 
121  sk_object.reset();
122  ASSERT_EQ(sk_object.get(), nullptr);
123  sk_object.reset();
124  ASSERT_EQ(sk_object.get(), nullptr);
125 
126  latch->Wait();
127  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
128 }
129 
130 } // namespace testing
131 } // namespace flutter
fml::RefPtr< SkiaUnrefQueue > unref_queue()
static constexpr TimeDelta FromSeconds(int64_t seconds)
Definition: time_delta.h:49
sk_sp< SkiaObjectType > get() const
Definition: ascii_trie.cc:9
static TaskQueueId GetCurrentTaskQueueId()
Definition: message_loop.cc:76
TestSkObject(std::shared_ptr< fml::AutoResetWaitableEvent > latch, fml::TaskQueueId *dtor_task_queue_id)
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)
RefPtr< T > MakeRefCounted(Args &&... args)
Definition: ref_ptr.h:244
A fixture that creates threads with running message loops that are terminated when the test is done (...
Definition: thread_test.h:27
fml::RefPtr< SkiaUnrefQueue > delayed_unref_queue()
fml::RefPtr< fml::TaskRunner > unref_task_runner()