Flutter Engine
 
Loading...
Searching...
No Matches
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
6
7#include <future>
8#include <utility>
9
14#include "gtest/gtest.h"
15#include "third_party/skia/include/core/SkRefCnt.h"
16#include "third_party/skia/include/gpu/ganesh/GrTypes.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) {}
46 void deleteBackendTexture(const GrBackendTexture& texture) {}
47 void flushAndSubmit(GrSyncCpu sync) {}
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 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
97 latch->Wait();
98 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
99}
100
101TEST_F(SkiaGpuObjectTest, ObjectDestructor) {
102 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
103 std::make_shared<fml::AutoResetWaitableEvent>();
104 fml::TaskQueueId dtor_task_queue_id(0);
105 auto object = sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id);
106 {
107 SkiaGPUObject<TestSkObject> sk_object(std::move(object), unref_queue());
108 // Verify that the default SkiaGPUObject dtor queues and unref.
109 }
110
111 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
112 latch->Wait();
113 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
114}
115
117 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
118 std::make_shared<fml::AutoResetWaitableEvent>();
119 fml::TaskQueueId dtor_task_queue_id(0);
121 sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
122 // Verify that explicitly resetting the GPU object queues and unref.
123 sk_object.reset();
124 ASSERT_EQ(sk_object.skia_object(), nullptr);
125 latch->Wait();
126 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
127}
128
129TEST_F(SkiaGpuObjectTest, ObjectResetTwice) {
130 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
131 std::make_shared<fml::AutoResetWaitableEvent>();
132 fml::TaskQueueId dtor_task_queue_id(0);
134 sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
135
136 sk_object.reset();
137 ASSERT_EQ(sk_object.skia_object(), nullptr);
138 sk_object.reset();
139 ASSERT_EQ(sk_object.skia_object(), nullptr);
140
141 latch->Wait();
142 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
143}
144
145TEST_F(SkiaGpuObjectTest, UnrefResourceContextInTaskRunnerThread) {
146 std::shared_ptr<fml::AutoResetWaitableEvent> latch =
147 std::make_shared<fml::AutoResetWaitableEvent>();
149 fml::TaskQueueId dtor_task_queue_id(0);
150 unref_task_runner()->PostTask([&]() {
151 auto resource_context =
152 sk_make_sp<TestResourceContext>(latch, &dtor_task_queue_id);
153 unref_queue = fml::MakeRefCounted<UnrefQueue<TestResourceContext>>(
154 unref_task_runner(), fml::TimeDelta::FromSeconds(0),
155 std::move(resource_context));
156 latch->Signal();
157 });
158 latch->Wait();
159
160 // Delete the unref queue, it will schedule a task to unref the resource
161 // context in the task runner's thread.
162 unref_queue = nullptr;
163 latch->Wait();
164 // Verify that the resource context was destroyed in the task runner's thread.
165 ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
166}
167
168} // namespace testing
169} // namespace flutter
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:26
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...
static TaskQueueId GetCurrentTaskQueueId()
virtual void PostTask(const fml::closure &task) override
static constexpr TimeDelta FromSeconds(int64_t seconds)
Definition time_delta.h:49
FlTexture * texture
TEST_F(DisplayListTest, Defaults)
Definition ref_ptr.h:261