Skip to content

Commit 6179c81

Browse files
authored
Linux texture support (flutter#24916)
1 parent 7d023e8 commit 6179c81

27 files changed

+1304
-7
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,9 @@ FILE: ../../../flutter/shell/platform/linux/fl_method_response.cc
15791579
FILE: ../../../flutter/shell/platform/linux/fl_method_response_test.cc
15801580
FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.cc
15811581
FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_plugin.h
1582+
FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc
1583+
FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h
1584+
FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc
15821585
FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc
15831586
FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.h
15841587
FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar.cc
@@ -1603,6 +1606,14 @@ FILE: ../../../flutter/shell/platform/linux/fl_task_runner.cc
16031606
FILE: ../../../flutter/shell/platform/linux/fl_task_runner.h
16041607
FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.cc
16051608
FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.h
1609+
FILE: ../../../flutter/shell/platform/linux/fl_texture.cc
1610+
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl.cc
1611+
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h
1612+
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_test.cc
1613+
FILE: ../../../flutter/shell/platform/linux/fl_texture_private.h
1614+
FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar.cc
1615+
FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar_private.h
1616+
FILE: ../../../flutter/shell/platform/linux/fl_texture_registrar_test.cc
16061617
FILE: ../../../flutter/shell/platform/linux/fl_value.cc
16071618
FILE: ../../../flutter/shell/platform/linux/fl_value_test.cc
16081619
FILE: ../../../flutter/shell/platform/linux/fl_view.cc
@@ -1624,11 +1635,15 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_call.
16241635
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h
16251636
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h
16261637
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h
1638+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_pixel_buffer_texture.h
16271639
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registrar.h
16281640
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h
16291641
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h
16301642
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h
16311643
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h
1644+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture.h
1645+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture_gl.h
1646+
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h
16321647
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h
16331648
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h
16341649
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h

shell/platform/linux/BUILD.gn

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,15 @@ _public_headers = [
5555
"public/flutter_linux/fl_method_channel.h",
5656
"public/flutter_linux/fl_method_codec.h",
5757
"public/flutter_linux/fl_method_response.h",
58+
"public/flutter_linux/fl_pixel_buffer_texture.h",
5859
"public/flutter_linux/fl_plugin_registrar.h",
5960
"public/flutter_linux/fl_plugin_registry.h",
6061
"public/flutter_linux/fl_standard_message_codec.h",
6162
"public/flutter_linux/fl_standard_method_codec.h",
6263
"public/flutter_linux/fl_string_codec.h",
64+
"public/flutter_linux/fl_texture.h",
65+
"public/flutter_linux/fl_texture_gl.h",
66+
"public/flutter_linux/fl_texture_registrar.h",
6367
"public/flutter_linux/fl_value.h",
6468
"public/flutter_linux/fl_view.h",
6569
"public/flutter_linux/flutter_linux.h",
@@ -114,6 +118,7 @@ source_set("flutter_linux_sources") {
114118
"fl_method_codec.cc",
115119
"fl_method_response.cc",
116120
"fl_mouse_cursor_plugin.cc",
121+
"fl_pixel_buffer_texture.cc",
117122
"fl_platform_plugin.cc",
118123
"fl_plugin_registrar.cc",
119124
"fl_plugin_registry.cc",
@@ -127,6 +132,9 @@ source_set("flutter_linux_sources") {
127132
"fl_task_runner.cc",
128133
"fl_task_runner.h",
129134
"fl_text_input_plugin.cc",
135+
"fl_texture.cc",
136+
"fl_texture_gl.cc",
137+
"fl_texture_registrar.cc",
130138
"fl_value.cc",
131139
"fl_view.cc",
132140
"fl_view_accessible.cc",
@@ -184,9 +192,12 @@ executable("flutter_linux_unittests") {
184192
"fl_method_channel_test.cc",
185193
"fl_method_codec_test.cc",
186194
"fl_method_response_test.cc",
195+
"fl_pixel_buffer_texture_test.cc",
187196
"fl_standard_message_codec_test.cc",
188197
"fl_standard_method_codec_test.cc",
189198
"fl_string_codec_test.cc",
199+
"fl_texture_gl_test.cc",
200+
"fl_texture_registrar_test.cc",
190201
"fl_value_test.cc",
191202
"testing/fl_test.cc",
192203
"testing/mock_engine.cc",

shell/platform/linux/fl_engine.cc

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88

99
#include <cstring>
1010

11+
#include "flutter/shell/platform/embedder/embedder.h"
1112
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
1213
#include "flutter/shell/platform/linux/fl_dart_project_private.h"
1314
#include "flutter/shell/platform/linux/fl_engine_private.h"
1415
#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h"
1516
#include "flutter/shell/platform/linux/fl_renderer.h"
1617
#include "flutter/shell/platform/linux/fl_renderer_headless.h"
1718
#include "flutter/shell/platform/linux/fl_settings_plugin.h"
19+
#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"
1820
#include "flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h"
1921

2022
// Unique number associated with platform tasks.
@@ -30,6 +32,7 @@ struct _FlEngine {
3032
FlRenderer* renderer;
3133
FlBinaryMessenger* binary_messenger;
3234
FlSettingsPlugin* settings_plugin;
35+
FlTextureRegistrar* texture_registrar;
3336
FlTaskRunner* task_runner;
3437
FlutterEngineAOTData aot_data;
3538
FLUTTER_API_SYMBOL(FlutterEngine) engine;
@@ -214,6 +217,26 @@ static bool fl_engine_gl_make_resource_current(void* user_data) {
214217
return result;
215218
}
216219

220+
// Called by the engine to retrieve an external texture.
221+
static bool fl_engine_gl_external_texture_frame_callback(
222+
void* user_data,
223+
int64_t texture_id,
224+
size_t width,
225+
size_t height,
226+
FlutterOpenGLTexture* texture) {
227+
FlEngine* self = static_cast<FlEngine*>(user_data);
228+
if (!self->texture_registrar) {
229+
return false;
230+
}
231+
g_autoptr(GError) error = nullptr;
232+
gboolean result = fl_texture_registrar_populate_gl_external_texture(
233+
self->texture_registrar, texture_id, width, height, texture, &error);
234+
if (!result) {
235+
g_warning("%s", error->message);
236+
}
237+
return result;
238+
}
239+
217240
// Called by the engine to determine if it is on the GTK thread.
218241
static bool fl_engine_runs_task_on_current_thread(void* user_data) {
219242
FlEngine* self = static_cast<FlEngine*>(user_data);
@@ -276,7 +299,8 @@ static FlPluginRegistrar* fl_engine_get_registrar_for_plugin(
276299
const gchar* name) {
277300
FlEngine* self = FL_ENGINE(registry);
278301

279-
return fl_plugin_registrar_new(nullptr, self->binary_messenger);
302+
return fl_plugin_registrar_new(nullptr, self->binary_messenger,
303+
self->texture_registrar);
280304
}
281305

282306
static void fl_engine_plugin_registry_iface_init(
@@ -299,6 +323,7 @@ static void fl_engine_dispose(GObject* object) {
299323

300324
g_clear_object(&self->project);
301325
g_clear_object(&self->renderer);
326+
g_clear_object(&self->texture_registrar);
302327
g_clear_object(&self->binary_messenger);
303328
g_clear_object(&self->settings_plugin);
304329
g_clear_object(&self->task_runner);
@@ -330,6 +355,7 @@ static void fl_engine_init(FlEngine* self) {
330355
self->embedder_api.struct_size = sizeof(FlutterEngineProcTable);
331356
FlutterEngineGetProcAddresses(&self->embedder_api);
332357

358+
self->texture_registrar = fl_texture_registrar_new(self);
333359
self->binary_messenger = fl_binary_messenger_new(self);
334360
}
335361

@@ -362,6 +388,8 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
362388
config.open_gl.fbo_callback = fl_engine_gl_get_fbo;
363389
config.open_gl.present = fl_engine_gl_present;
364390
config.open_gl.make_resource_current = fl_engine_gl_make_resource_current;
391+
config.open_gl.gl_external_texture_frame_callback =
392+
fl_engine_gl_external_texture_frame_callback;
365393

366394
FlutterTaskRunnerDescription platform_task_runner = {};
367395
platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription);
@@ -673,6 +701,27 @@ void fl_engine_dispatch_semantics_action(FlEngine* self,
673701
action_data, action_data_length);
674702
}
675703

704+
gboolean fl_engine_mark_texture_frame_available(FlEngine* self,
705+
int64_t texture_id) {
706+
g_return_val_if_fail(FL_IS_ENGINE(self), FALSE);
707+
return self->embedder_api.MarkExternalTextureFrameAvailable(
708+
self->engine, texture_id) == kSuccess;
709+
}
710+
711+
gboolean fl_engine_register_external_texture(FlEngine* self,
712+
int64_t texture_id) {
713+
g_return_val_if_fail(FL_IS_ENGINE(self), FALSE);
714+
return self->embedder_api.RegisterExternalTexture(self->engine, texture_id) ==
715+
kSuccess;
716+
}
717+
718+
gboolean fl_engine_unregister_external_texture(FlEngine* self,
719+
int64_t texture_id) {
720+
g_return_val_if_fail(FL_IS_ENGINE(self), FALSE);
721+
return self->embedder_api.UnregisterExternalTexture(self->engine,
722+
texture_id) == kSuccess;
723+
}
724+
676725
G_MODULE_EXPORT FlBinaryMessenger* fl_engine_get_binary_messenger(
677726
FlEngine* self) {
678727
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
@@ -688,3 +737,9 @@ void fl_engine_execute_task(FlEngine* self, FlutterTask* task) {
688737
g_return_if_fail(FL_IS_ENGINE(self));
689738
self->embedder_api.RunTask(self->engine, task);
690739
}
740+
741+
G_MODULE_EXPORT FlTextureRegistrar* fl_engine_get_texture_registrar(
742+
FlEngine* self) {
743+
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
744+
return self->texture_registrar;
745+
}

shell/platform/linux/fl_engine_private.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,44 @@ FlTaskRunner* fl_engine_get_task_runner(FlEngine* engine);
253253
*/
254254
void fl_engine_execute_task(FlEngine* engine, FlutterTask* task);
255255

256+
/**
257+
* fl_engine_mark_texture_frame_available:
258+
* @engine: an #FlEngine.
259+
* @texture_id: the identifier of the texture whose frame has been updated.
260+
*
261+
* Tells the Flutter engine that a new texture frame is available for the given
262+
* texture.
263+
*
264+
* Returns: %TRUE on success.
265+
*/
266+
gboolean fl_engine_mark_texture_frame_available(FlEngine* engine,
267+
int64_t texture_id);
268+
269+
/**
270+
* fl_engine_register_external_texture:
271+
* @engine: an #FlEngine.
272+
* @texture_id: the identifier of the texture that is available.
273+
*
274+
* Tells the Flutter engine that a new external texture is available.
275+
*
276+
* Returns: %TRUE on success.
277+
*/
278+
gboolean fl_engine_register_external_texture(FlEngine* engine,
279+
int64_t texture_id);
280+
281+
/**
282+
* fl_engine_unregister_external_texture:
283+
* @engine: an #FlEngine.
284+
* @texture_id: the identifier of the texture that is not available anymore.
285+
*
286+
* Tells the Flutter engine that an existing external texture is not available
287+
* anymore.
288+
*
289+
* Returns: %TRUE on success.
290+
*/
291+
gboolean fl_engine_unregister_external_texture(FlEngine* engine,
292+
int64_t texture_id);
293+
256294
G_END_DECLS
257295

258296
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_PRIVATE_H_
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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_pixel_buffer_texture.h"
6+
7+
#include <epoxy/gl.h>
8+
#include <gmodule.h>
9+
10+
#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h"
11+
12+
typedef struct {
13+
GLuint texture_id;
14+
} FlPixelBufferTexturePrivate;
15+
16+
// Added here to stop the compiler from optimising this function away.
17+
G_MODULE_EXPORT GType fl_pixel_buffer_texture_get_type();
18+
19+
static void fl_pixel_buffer_texture_iface_init(FlTextureInterface* iface) {}
20+
21+
G_DEFINE_TYPE_WITH_CODE(
22+
FlPixelBufferTexture,
23+
fl_pixel_buffer_texture,
24+
G_TYPE_OBJECT,
25+
G_IMPLEMENT_INTERFACE(fl_texture_get_type(),
26+
fl_pixel_buffer_texture_iface_init);
27+
G_ADD_PRIVATE(FlPixelBufferTexture))
28+
29+
static void fl_pixel_buffer_texture_dispose(GObject* object) {
30+
FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(object);
31+
FlPixelBufferTexturePrivate* priv =
32+
reinterpret_cast<FlPixelBufferTexturePrivate*>(
33+
fl_pixel_buffer_texture_get_instance_private(self));
34+
35+
if (priv->texture_id) {
36+
glDeleteTextures(1, &priv->texture_id);
37+
priv->texture_id = 0;
38+
}
39+
40+
G_OBJECT_CLASS(fl_pixel_buffer_texture_parent_class)->dispose(object);
41+
}
42+
43+
static void check_gl_error(int line) {
44+
GLenum err = glGetError();
45+
if (err) {
46+
g_warning("glGetError %x (%s:%d)\n", err, __FILE__, line);
47+
}
48+
}
49+
50+
gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture,
51+
uint32_t width,
52+
uint32_t height,
53+
FlutterOpenGLTexture* opengl_texture,
54+
GError** error) {
55+
FlPixelBufferTexture* self = FL_PIXEL_BUFFER_TEXTURE(texture);
56+
FlPixelBufferTexturePrivate* priv =
57+
reinterpret_cast<FlPixelBufferTexturePrivate*>(
58+
fl_pixel_buffer_texture_get_instance_private(self));
59+
60+
const uint8_t* buffer = nullptr;
61+
if (!FL_PIXEL_BUFFER_TEXTURE_GET_CLASS(self)->copy_pixels(
62+
self, &buffer, &width, &height, error)) {
63+
return FALSE;
64+
}
65+
66+
if (priv->texture_id == 0) {
67+
glGenTextures(1, &priv->texture_id);
68+
check_gl_error(__LINE__);
69+
glBindTexture(GL_TEXTURE_2D, priv->texture_id);
70+
check_gl_error(__LINE__);
71+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
72+
check_gl_error(__LINE__);
73+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
74+
check_gl_error(__LINE__);
75+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
76+
check_gl_error(__LINE__);
77+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
78+
check_gl_error(__LINE__);
79+
} else {
80+
glBindTexture(GL_TEXTURE_2D, priv->texture_id);
81+
check_gl_error(__LINE__);
82+
}
83+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA,
84+
GL_UNSIGNED_BYTE, buffer);
85+
check_gl_error(__LINE__);
86+
87+
opengl_texture->target = GL_TEXTURE_2D;
88+
opengl_texture->name = priv->texture_id;
89+
opengl_texture->format = GL_RGBA8;
90+
opengl_texture->destruction_callback = nullptr;
91+
opengl_texture->user_data = nullptr;
92+
opengl_texture->width = width;
93+
opengl_texture->height = height;
94+
95+
return TRUE;
96+
}
97+
98+
static void fl_pixel_buffer_texture_class_init(
99+
FlPixelBufferTextureClass* klass) {
100+
G_OBJECT_CLASS(klass)->dispose = fl_pixel_buffer_texture_dispose;
101+
}
102+
103+
static void fl_pixel_buffer_texture_init(FlPixelBufferTexture* self) {}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_PRIVATE_H_
6+
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_PRIVATE_H_
7+
8+
#include "flutter/shell/platform/embedder/embedder.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_registrar.h"
11+
12+
G_BEGIN_DECLS
13+
14+
/**
15+
* fl_pixel_buffer_texture_populate:
16+
* @texture: an #FlPixelBufferTexture.
17+
* @width: width of the texture.
18+
* @height: height of the texture.
19+
* @opengl_texture: (out): return an #FlutterOpenGLTexture.
20+
* @error: (allow-none): #GError location to store the error occurring, or
21+
* %NULL to ignore.
22+
*
23+
* Attempts to populate the specified @opengl_texture with texture details
24+
* such as the name, width, height and the pixel format.
25+
*
26+
* Returns: %TRUE on success.
27+
*/
28+
gboolean fl_pixel_buffer_texture_populate(FlPixelBufferTexture* texture,
29+
uint32_t width,
30+
uint32_t height,
31+
FlutterOpenGLTexture* opengl_texture,
32+
GError** error);
33+
34+
G_END_DECLS
35+
36+
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PIXEL_BUFFER_TEXTURE_PRIVATE_H_

0 commit comments

Comments
 (0)