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 
6 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
11 #include "flutter/shell/platform/linux/testing/linux_test.h"
12 #include "flutter/shell/platform/linux/testing/mock_texture_registrar.h"
13 #include "gtest/gtest.h"
14 
15 #include <epoxy/gl.h>
16 
17 #include <gmodule.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;
54 
55  return TRUE;
56 }
57 
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 gpointer add_mock_texture_to_registrar(gpointer pointer) {
71  g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(pointer), nullptr);
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 = g_new0(int64_t, 1);
76  id[0] = fl_texture_get_id(texture);
77  return id;
78 }
79 
80 class FlTextureRegistrarTest : public flutter::testing::LinuxTest {};
81 
82 // Checks can make a mock registrar.
83 TEST_F(FlTextureRegistrarTest, MockRegistrar) {
84  g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
85  g_autoptr(FlMockTextureRegistrar) registrar = fl_mock_texture_registrar_new();
86  EXPECT_TRUE(FL_IS_MOCK_TEXTURE_REGISTRAR(registrar));
87 
89  FL_TEXTURE_REGISTRAR(registrar), texture));
90  EXPECT_EQ(fl_mock_texture_registrar_get_texture(registrar), texture);
92  FL_TEXTURE_REGISTRAR(registrar), texture));
93  EXPECT_TRUE(fl_mock_texture_registrar_get_frame_available(registrar));
95  FL_TEXTURE_REGISTRAR(registrar), texture));
96  EXPECT_EQ(fl_mock_texture_registrar_get_texture(registrar), nullptr);
97 }
98 
99 // Test that registering a texture works.
100 TEST_F(FlTextureRegistrarTest, RegisterTexture) {
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_F(FlTextureRegistrarTest, MarkTextureFrameAvailable) {
130  bool register_called = false;
131  fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
132  MOCK_ENGINE_PROC(RegisterExternalTexture,
133  ([&register_called](auto engine, int64_t texture_id) {
134  register_called = true;
135  return kSuccess;
136  }));
137  fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
138  MOCK_ENGINE_PROC(
139  UnregisterExternalTexture,
140  ([](auto engine, int64_t texture_id) { return kSuccess; }));
141  fl_engine_get_embedder_api(engine)->MarkExternalTextureFrameAvailable =
142  MOCK_ENGINE_PROC(
143  MarkExternalTextureFrameAvailable,
144  ([](auto engine, int64_t texture_id) { return kSuccess; }));
145 
146  g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
147  g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
148 
149  EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture));
150  EXPECT_TRUE(register_called);
151  EXPECT_TRUE(
153 }
154 
155 // Test handles error marking a texture frame available.
156 TEST_F(FlTextureRegistrarTest, MarkInvalidTextureFrameAvailable) {
157  fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
158  MOCK_ENGINE_PROC(
159  RegisterExternalTexture,
160  ([](auto engine, int64_t texture_id) { return kSuccess; }));
161  fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
162  MOCK_ENGINE_PROC(
163  UnregisterExternalTexture,
164  ([](auto engine, int64_t texture_id) { return kSuccess; }));
165  fl_engine_get_embedder_api(engine)->MarkExternalTextureFrameAvailable =
166  MOCK_ENGINE_PROC(MarkExternalTextureFrameAvailable,
167  ([](auto engine, int64_t texture_id) {
168  return kInternalInconsistency;
169  }));
170 
171  g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
172  g_autoptr(FlTexture) texture = FL_TEXTURE(fl_test_registrar_texture_new());
173 
174  EXPECT_TRUE(fl_texture_registrar_register_texture(registrar, texture));
175  EXPECT_FALSE(
177 }
178 
179 // Test the textures can be accessed via multiple threads without
180 // synchronization issues.
181 TEST_F(FlTextureRegistrarTest, RegistrarRegisterTextureInMultipleThreads) {
182  fl_engine_get_embedder_api(engine)->RegisterExternalTexture =
183  MOCK_ENGINE_PROC(
184  RegisterExternalTexture,
185  ([](auto engine, int64_t texture_id) { return kSuccess; }));
186  fl_engine_get_embedder_api(engine)->UnregisterExternalTexture =
187  MOCK_ENGINE_PROC(
188  UnregisterExternalTexture,
189  ([](auto engine, int64_t texture_id) { return kSuccess; }));
190 
191  g_autoptr(FlTextureRegistrar) registrar = fl_texture_registrar_new(engine);
192  GThread* threads[kThreadCount];
193  int64_t ids[kThreadCount];
194 
195  for (uint64_t t = 0; t < kThreadCount; t++) {
196  threads[t] =
197  g_thread_new(nullptr, add_mock_texture_to_registrar, registrar);
198  ASSERT_NE(threads[t], nullptr);
199  }
200  for (uint64_t t = 0; t < kThreadCount; t++) {
201  g_autofree int64_t* id = static_cast<int64_t*>(g_thread_join(threads[t]));
202  ASSERT_NE(id, nullptr);
203  ids[t] = *id;
204  }
205  // Check all the textures were created.
206  for (uint64_t t = 0; t < kThreadCount; t++) {
207  EXPECT_TRUE(fl_texture_registrar_lookup_texture(registrar, ids[t]) != NULL);
208  }
209 }
g_autoptr(FlEngine) engine
GLuint texture_id
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:940
int64_t id
G_MODULE_EXPORT int64_t fl_texture_get_id(FlTexture *self)
Definition: fl_texture.cc:20
G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(FlTextureRegistrar *self, FlTexture *texture)
G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(FlTextureRegistrar *self, FlTexture *texture)
G_MODULE_EXPORT gboolean fl_texture_registrar_mark_texture_frame_available(FlTextureRegistrar *self, FlTexture *texture)
FlTextureRegistrar * fl_texture_registrar_new(FlEngine *engine)
FlTexture * fl_texture_registrar_lookup_texture(FlTextureRegistrar *self, int64_t texture_id)
uint32_t uint32_t uint32_t uint32_t GError ** error
TEST_F(FlTextureRegistrarTest, MockRegistrar)
static void fl_test_registrar_texture_init(FlTestRegistrarTexture *self)
static FlTestRegistrarTexture * fl_test_registrar_texture_new()
static gpointer add_mock_texture_to_registrar(gpointer pointer)
static constexpr uint32_t kBufferWidth
uint32_t uint32_t uint32_t uint32_t * height
uint32_t uint32_t * format
uint32_t uint32_t uint32_t * width
G_DEFINE_TYPE(FlTestRegistrarTexture, fl_test_registrar_texture, fl_texture_gl_get_type()) static gboolean fl_test_registrar_texture_populate(FlTextureGL *texture
static constexpr uint32_t kRealBufferHeight
G_DECLARE_FINAL_TYPE(FlTestRegistrarTexture, fl_test_registrar_texture, FL, TEST_REGISTRAR_TEXTURE, FlTextureGL) struct _FlTestRegistrarTexture
A simple texture.
static void fl_test_registrar_texture_class_init(FlTestRegistrarTextureClass *klass)
static constexpr uint32_t kBufferHeight
static constexpr uint64_t kThreadCount
static constexpr uint32_t kRealBufferWidth
uint32_t * target