| Flutter Linux Embedder |

fl_texture_registrar_test.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/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h"
6 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
7 #include "flutter/shell/platform/linux/fl_engine_private.h"
8 #include "flutter/shell/platform/linux/fl_texture_registrar_private.h"
9 #include "flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h"
10 #include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_gl.h"
11 #include "flutter/shell/platform/linux/testing/mock_texture_registrar.h"
12 #include "gtest/gtest.h"
13
14 #include <epoxy/gl.h>
15
16 #include <gmodule.h>
17 #include <pthread.h>
18
19 static constexpr uint32_t kBufferWidth = 4u;
20 static constexpr uint32_t kBufferHeight = 4u;
21 static constexpr uint32_t kRealBufferWidth = 2u;
22 static constexpr uint32_t kRealBufferHeight = 2u;
23 static constexpr uint64_t kThreadCount = 16u;
24
25 G_DECLARE_FINAL_TYPE(FlTestRegistrarTexture,
26 fl_test_registrar_texture,
27 FL,
28 TEST_REGISTRAR_TEXTURE,
29 FlTextureGL)
30
31 /// A simple texture.
32 struct _FlTestRegistrarTexture {
33 FlTextureGL parent_instance;
34 };
35
36 G_DEFINE_TYPE(FlTestRegistrarTexture,
37 fl_test_registrar_texture,
38 fl_texture_gl_get_type())
39
40 static gboolean fl_test_registrar_texture_populate(FlTextureGL* texture,
41 uint32_t* target,
42 uint32_t* format,
43 uint32_t* width,
44 uint32_t* height,
45 GError** error) {
46 EXPECT_TRUE(FL_IS_TEST_REGISTRAR_TEXTURE(texture));
47
48 EXPECT_EQ(*width, kBufferWidth);
49 EXPECT_EQ(*height, kBufferHeight);
50 *target = GL_TEXTURE_2D;
51 *format = GL_R8;
52 *width = kRealBufferWidth;
53 *height = kRealBufferHeight;
54
55 return TRUE;
56 }
57
58 static void fl_test_registrar_texture_class_init(
59 FlTestRegistrarTextureClass* klass) {
60 FL_TEXTURE_GL_CLASS(klass)->populate = fl_test_registrar_texture_populate;
61 }
62
63 static void fl_test_registrar_texture_init(FlTestRegistrarTexture* self) {}
64
65 static FlTestRegistrarTexture* fl_test_registrar_texture_new() {
66 return FL_TEST_REGISTRAR_TEXTURE(
67 g_object_new(fl_test_registrar_texture_get_type(), nullptr));
68 }
69
70 static void* add_mock_texture_to_registrar(void* pointer) {
71 g_return_val_if_fail(FL_TEXTURE_REGISTRAR(pointer), ((void*)NULL));
72 FlTextureRegistrar* registrar = FL_TEXTURE_REGISTRAR(pointer);
73 g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
74 fl_texture_registrar_register_texture(registrar, texture);
75 int64_t* id = static_cast<int64_t*>(malloc(sizeof(int64_t)));
76 id[0] = fl_texture_get_id(texture);
77 pthread_exit(id);
78 }
79
80 // Checks can make a mock registrar.
81 TEST(FlTextureRegistrarTest, MockRegistrar) {
82 g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
83 g_autoptr(FlMockTextureRegistrar) registrar = fl_mock_texture_registrar_new();
84 EXPECT_TRUE(FL_IS_MOCK_TEXTURE_REGISTRAR(registrar));
85
86 EXPECT_TRUE(fl_texture_registrar_register_texture(
87 FL_TEXTURE_REGISTRAR(registrar), texture));
88 EXPECT_EQ(fl_mock_texture_registrar_get_texture(registrar), texture);
89 EXPECT_TRUE(fl_texture_registrar_mark_texture_frame_available(
90 FL_TEXTURE_REGISTRAR(registrar), texture));
91 EXPECT_TRUE(fl_mock_texture_registrar_get_frame_available(registrar));
92 EXPECT_TRUE(fl_texture_registrar_unregister_texture(
93 FL_TEXTURE_REGISTRAR(registrar), texture));
94 EXPECT_EQ(fl_mock_texture_registrar_get_texture(registrar), nullptr);
95 }
96
97 // Test that registering a texture works.
98 TEST(FlTextureRegistrarTest, RegisterTexture) {
99 g_autoptr(FlDartProject) project = fl_dart_project_new();
100 g_autoptr(FlEngine) engine = fl_engine_new(project);
101 bool register_called = false;
102 fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
103 MOCK_ENGINE_PROC(RegisterExternalTexture,
104 ([&register_called](auto engine, int64_t texture_id) {
105 register_called = true;
106 return kSuccess;
107 }));
108 bool unregister_called = false;
109 fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
110 MOCK_ENGINE_PROC(UnregisterExternalTexture,
111 ([&unregister_called](auto engine, int64_t texture_id) {
112 unregister_called = true;
113 return kSuccess;
114 }));
115
116 g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
117 g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
118
119 // EXPECT_FALSE(fl_texture_registrar_unregister_texture(registrar, texture));
120 EXPECT_FALSE(register_called);
121 EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture));
122 EXPECT_TRUE(register_called);
123 EXPECT_FALSE(unregister_called);
124 EXPECT_TRUE(fl_texture_registrar_unregister_texture(registrar, texture));
125 EXPECT_TRUE(unregister_called);
126 }
127
128 // Test that marking a texture frame available works.
129 TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) {
130 g_autoptr(FlDartProject) project = fl_dart_project_new();
131 g_autoptr(FlEngine) engine = fl_engine_new(project);
132 bool register_called = false;
133 fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
134 MOCK_ENGINE_PROC(RegisterExternalTexture,
135 ([&register_called](auto engine, int64_t texture_id) {
136 register_called = true;
137 return kSuccess;
138 }));
139 fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
140 MOCK_ENGINE_PROC(
141 UnregisterExternalTexture,
142 ([](auto engine, int64_t texture_id) { return kSuccess; }));
143 fl_engine_get_embedder_api(engine)->MarkExternalTextureFrameAvailable =
144 MOCK_ENGINE_PROC(MarkExternalTextureFrameAvailable,
145 ([](auto engine, int64_t texture_id) {
146 g_printerr("!\n");
147 return kSuccess;
148 }));
149
150 g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
151 g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
152
153 EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture));
154 EXPECT_TRUE(register_called);
155 EXPECT_TRUE(
156 fl_texture_registrar_mark_texture_frame_available(registrar, texture));
157 }
158
159 // Test handles error marking a texture frame available.
160 TEST(FlTextureRegistrarTest, MarkInvalidTextureFrameAvailable) {
161 g_autoptr(FlDartProject) project = fl_dart_project_new();
162 g_autoptr(FlEngine) engine = fl_engine_new(project);
163 fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
164 MOCK_ENGINE_PROC(
165 RegisterExternalTexture,
166 ([](auto engine, int64_t texture_id) { return kSuccess; }));
167 fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
168 MOCK_ENGINE_PROC(
169 UnregisterExternalTexture,
170 ([](auto engine, int64_t texture_id) { return kSuccess; }));
171 fl_engine_get_embedder_api(engine)->MarkExternalTextureFrameAvailable =
172 MOCK_ENGINE_PROC(MarkExternalTextureFrameAvailable,
173 ([](auto engine, int64_t texture_id) {
174 return kInternalInconsistency;
175 }));
176
177 g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
178 g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
179
180 EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture));
181 EXPECT_FALSE(
182 fl_texture_registrar_mark_texture_frame_available(registrar, texture));
183 }
184
185 // Test the textures can be accessed via multiple threads without
186 // synchronization issues.
187 // TODO(robert-ancell): Re-enable when no longer flaky
188 // https://github.com/flutter/flutter/issues/138197
189 TEST(FlTextureRegistrarTest,
190 DISABLED_RegistrarRegisterTextureInMultipleThreads) {
191 g_autoptr(FlDartProject) project = fl_dart_project_new();
192 g_autoptr(FlEngine) engine = fl_engine_new(project);
193
194 fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
195 MOCK_ENGINE_PROC(
196 RegisterExternalTexture,
197 ([](auto engine, int64_t texture_id) { return kSuccess; }));
198 fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
199 MOCK_ENGINE_PROC(
200 UnregisterExternalTexture,
201 ([](auto engine, int64_t texture_id) { return kSuccess; }));
202
203 g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
204 pthread_t threads[kThreadCount];
205 int64_t ids[kThreadCount];
206
207 for (uint64_t t = 0; t < kThreadCount; t++) {
208 EXPECT_EQ(pthread_create(&threads[t], NULL, add_mock_texture_to_registrar,
209 (void*)registrar),
210 0);
211 }
212 for (uint64_t t = 0; t < kThreadCount; t++) {
213 void* id;
214 pthread_join(threads[t], &id);
215 ids[t] = static_cast<int64_t*>(id)[0];
216 free(id);
217 };
218 // Check all the textures were created.
219 for (uint64_t t = 0; t < kThreadCount; t++) {
220 EXPECT_TRUE(fl_texture_registrar_lookup_texture(registrar, ids[t]) != NULL);
221 };
222 }
add_mock_texture_to_registrar
static void * add_mock_texture_to_registrar(void *pointer)
Definition: fl_texture_registrar_test.cc:70
fl_engine_get_embedder_api
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:661
kBufferHeight
static constexpr uint32_t kBufferHeight
Definition: fl_texture_registrar_test.cc:20
kRealBufferWidth
static constexpr uint32_t kRealBufferWidth
Definition: fl_texture_registrar_test.cc:21
fl_texture_registrar_lookup_texture
FlTexture * fl_texture_registrar_lookup_texture(FlTextureRegistrar *self, int64_t texture_id)
Definition: fl_texture_registrar.cc:190
fl_pixel_buffer_texture.h
fl_test_registrar_texture_new
static FlTestRegistrarTexture * fl_test_registrar_texture_new()
Definition: fl_texture_registrar_test.cc:65
id
int64_t id
Definition: fl_pixel_buffer_texture.cc:28
kRealBufferHeight
static constexpr uint32_t kRealBufferHeight
Definition: fl_texture_registrar_test.cc:22
fl_texture_registrar_new
FlTextureRegistrar * fl_texture_registrar_new(FlEngine *engine)
Definition: fl_texture_registrar.cc:221
fl_dart_project_new
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
Definition: fl_dart_project.cc:50
fl_texture_registrar_unregister_texture
G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:206
error
uint32_t uint32_t uint32_t uint32_t GError ** error
Definition: fl_texture_registrar_test.cc:45
TRUE
return TRUE
Definition: fl_texture_registrar_test.cc:55
fl_texture_registrar_register_texture
G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:181
fl_engine_private.h
fl_texture_registrar.h
fl_test_registrar_texture_class_init
static void fl_test_registrar_texture_class_init(FlTestRegistrarTextureClass *klass)
Definition: fl_texture_registrar_test.cc:58
fl_texture_gl.h
fl_texture_get_id
G_MODULE_EXPORT int64_t fl_texture_get_id(FlTexture *self)
Definition: fl_texture.cc:20
kBufferWidth
static constexpr uint32_t kBufferWidth
Definition: fl_texture_registrar_test.cc:19
FL
FL
Definition: fl_binary_messenger.cc:27
width
uint32_t uint32_t uint32_t * width
Definition: fl_texture_registrar_test.cc:43
height
uint32_t uint32_t uint32_t uint32_t * height
Definition: fl_texture_registrar_test.cc:44
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlTestRegistrarTexture, fl_test_registrar_texture, FL, TEST_REGISTRAR_TEXTURE, FlTextureGL) struct _FlTestRegistrarTexture
A simple texture.
Definition: fl_texture_registrar_test.cc:25
fl_engine_new
G_MODULE_EXPORT FlEngine * fl_engine_new(FlDartProject *project)
Definition: fl_engine.cc:524
kThreadCount
static constexpr uint64_t kThreadCount
Definition: fl_texture_registrar_test.cc:23
target
uint32_t * target
Definition: fl_texture_registrar_test.cc:41
G_DEFINE_TYPE
G_DEFINE_TYPE(FlTestRegistrarTexture, fl_test_registrar_texture, fl_texture_gl_get_type()) static gboolean fl_test_registrar_texture_populate(FlTextureGL *texture
fl_texture_registrar_private.h
fl_test_registrar_texture_init
static void fl_test_registrar_texture_init(FlTestRegistrarTexture *self)
Definition: fl_texture_registrar_test.cc:63
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
format
uint32_t uint32_t * format
Definition: fl_texture_registrar_test.cc:42
TEST
TEST(FlTextureRegistrarTest, MockRegistrar)
Definition: fl_texture_registrar_test.cc:81
fl_texture_registrar_mark_texture_frame_available
G_MODULE_EXPORT gboolean fl_texture_registrar_mark_texture_frame_available(FlTextureRegistrar *self, FlTexture *texture)
Definition: fl_texture_registrar.cc:197