Flutter Engine
The 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#include <utility>
9
10#include "flutter/fml/message_loop.h"
11#include "flutter/fml/synchronization/waitable_event.h"
12#include "flutter/fml/task_runner.h"
13#include "flutter/testing/thread_test.h"
14#include "gtest/gtest.h"
17
18namespace flutter {
19namespace testing {
20
21class TestSkObject : public SkRefCnt {
22 public:
23 TestSkObject(std::shared_ptr<fml::AutoResetWaitableEvent> latch,
24 fml::TaskQueueId* dtor_task_queue_id)
25 : latch_(std::move(latch)), dtor_task_queue_id_(dtor_task_queue_id) {}
26
27 virtual ~TestSkObject() {
28 if (dtor_task_queue_id_) {
29 *dtor_task_queue_id_ = fml::MessageLoop::GetCurrentTaskQueueId();
30 }
31 latch_->Signal();
32 }
33
34 private:
35 std::shared_ptr<fml::AutoResetWaitableEvent> latch_;
36 fml::TaskQueueId* dtor_task_queue_id_;
37};
38
40 public:
41 TestResourceContext(std::shared_ptr<fml::AutoResetWaitableEvent> latch,
42 fml::TaskQueueId* dtor_task_queue_id)
43 : TestSkObject(std::move(latch), dtor_task_queue_id) {}
45 void performDeferredCleanup(std::chrono::milliseconds msNotUsed) {}
48};
49
51 public:
53 : unref_task_runner_(CreateNewThread()),
54 unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
56 fml::TimeDelta::FromSeconds(0))),
57 delayed_unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
59 fml::TimeDelta::FromSeconds(3))) {
60 // The unref queues must be created in the same thread of the
61 // unref_task_runner so the queue can access the same-thread-only WeakPtr of
62 // the GrContext constructed during the creation.
63 std::promise<bool> queues_created;
64 unref_task_runner_->PostTask([this, &queues_created]() {
65 unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
67 delayed_unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
69 queues_created.set_value(true);
70 });
71 queues_created.get_future().wait();
72 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
73 }
74
76 return unref_task_runner_;
77 }
78 fml::RefPtr<SkiaUnrefQueue> unref_queue() { return unref_queue_; }
80 return delayed_unref_queue_;
81 }
82
83 private:
84 fml::RefPtr<fml::TaskRunner> unref_task_runner_;
85 fml::RefPtr<SkiaUnrefQueue> unref_queue_;
86 fml::RefPtr<SkiaUnrefQueue> delayed_unref_queue_;
87};
88
90 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
91 std::make_shared<fml::AutoResetWaitableEvent>();
92 fml::TaskQueueId dtor_task_queue_id(0);
93 SkRefCnt* ref_object = new TestSkObject(latch, &dtor_task_queue_id);
94
95 unref_queue()->Unref(ref_object);
96 latch->Wait();
97 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
98}
99
100TEST_F(SkiaGpuObjectTest, ObjectDestructor) {
101 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
102 std::make_shared<fml::AutoResetWaitableEvent>();
103 fml::TaskQueueId dtor_task_queue_id(0);
104 auto object = sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id);
105 {
106 SkiaGPUObject<TestSkObject> sk_object(std::move(object), unref_queue());
107 // Verify that the default SkiaGPUObject dtor queues and unref.
108 }
109
110 latch->Wait();
111 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
112}
113
115 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
116 std::make_shared<fml::AutoResetWaitableEvent>();
117 fml::TaskQueueId dtor_task_queue_id(0);
119 sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
120 // Verify that explicitly resetting the GPU object queues and unref.
121 sk_object.reset();
122 ASSERT_EQ(sk_object.skia_object(), nullptr);
123 latch->Wait();
124 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
125}
126
127TEST_F(SkiaGpuObjectTest, ObjectResetTwice) {
128 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
129 std::make_shared<fml::AutoResetWaitableEvent>();
130 fml::TaskQueueId dtor_task_queue_id(0);
132 sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
133
134 sk_object.reset();
135 ASSERT_EQ(sk_object.skia_object(), nullptr);
136 sk_object.reset();
137 ASSERT_EQ(sk_object.skia_object(), nullptr);
138
139 latch->Wait();
140 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
141}
142
143TEST_F(SkiaGpuObjectTest, UnrefResourceContextInTaskRunnerThread) {
144 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
145 std::make_shared<fml::AutoResetWaitableEvent>();
147 fml::TaskQueueId dtor_task_queue_id(0);
148 unref_task_runner()->PostTask([&]() {
149 auto resource_context =
150 sk_make_sp<TestResourceContext>(latch, &dtor_task_queue_id);
151 unref_queue = fml::MakeRefCounted<UnrefQueue<TestResourceContext>>(
152 unref_task_runner(), fml::TimeDelta::FromSeconds(0),
153 std::move(resource_context));
154 latch->Signal();
155 });
156 latch->Wait();
157
158 // Delete the unref queue, it will schedule a task to unref the resource
159 // context in the task runner's thread.
160 unref_queue = nullptr;
161 latch->Wait();
162 // Verify that the resource context was destroyed in the task runner's thread.
163 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
164}
165
166} // namespace testing
167} // namespace flutter
GrSyncCpu
Definition: GrTypes.h:239
sk_sp< SkiaObjectType > skia_object() const
fml::RefPtr< fml::TaskRunner > unref_task_runner()
fml::RefPtr< SkiaUnrefQueue > unref_queue()
fml::RefPtr< SkiaUnrefQueue > delayed_unref_queue()
void deleteBackendTexture(const GrBackendTexture &texture)
TestResourceContext(std::shared_ptr< fml::AutoResetWaitableEvent > latch, fml::TaskQueueId *dtor_task_queue_id)
void performDeferredCleanup(std::chrono::milliseconds msNotUsed)
TestSkObject(std::shared_ptr< fml::AutoResetWaitableEvent > latch, fml::TaskQueueId *dtor_task_queue_id)
A fixture that creates threads with running message loops that are terminated when the test is done (...
Definition: thread_test.h:27
fml::RefPtr< fml::TaskRunner > CreateNewThread(const std::string &name="")
Creates a new thread, initializes a message loop on it, and, returns its task runner to the unit-test...
Definition: thread_test.cc:26
static TaskQueueId GetCurrentTaskQueueId()
Definition: message_loop.cc:76
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
static constexpr TimeDelta FromSeconds(int64_t seconds)
Definition: time_delta.h:49
FlTexture * texture
TEST_F(DisplayListTest, Defaults)
Definition: ascii_trie.cc:9
RefPtr< T > MakeRefCounted(Args &&... args)
Definition: ref_ptr.h:248
Definition: ref_ptr.h:256