Skip to content

Commit 32f2bc3

Browse files
authored
Support EmbedderExternalTextureGL for impeller (#69)
1 parent 36f818a commit 32f2bc3

10 files changed

+374
-15
lines changed

flutter/shell/platform/embedder/embedder.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ typedef struct {
294294
} FlutterTransformation;
295295

296296
typedef void (*VoidCallback)(void* /* user data */);
297+
typedef bool (*BoolCallback)(void* /* user data */);
297298

298299
typedef enum {
299300
/// Specifies an OpenGL texture target type. Textures are specified using
@@ -361,6 +362,11 @@ typedef enum {
361362
kFlutterSoftwarePixelFormatNative32,
362363
} FlutterSoftwarePixelFormat;
363364

365+
typedef enum {
366+
kFlutterGLImpellerTexturePixelBuffer,
367+
kFlutterGLImpellerTextureGpuSurface,
368+
} FlutterGLImpellerTextureType;
369+
364370
typedef struct {
365371
/// Target texture of the active texture unit (example GL_TEXTURE_2D or
366372
/// GL_TEXTURE_RECTANGLE).
@@ -369,6 +375,14 @@ typedef struct {
369375
uint32_t name;
370376
/// The texture format (example GL_RGBA8).
371377
uint32_t format;
378+
/// The pixel data buffer.
379+
const uint8_t* buffer;
380+
/// The size of pixel buffer.
381+
size_t buffer_size;
382+
/// Callback invoked that the gpu surface texture start binding.
383+
BoolCallback bind_callback;
384+
/// The type of the texture.
385+
FlutterGLImpellerTextureType impeller_texture_type;
372386
/// User data to be returned on the invocation of the destruction callback.
373387
void* user_data;
374388
/// Callback invoked (on an engine managed thread) that asks the embedder to
@@ -401,7 +415,6 @@ typedef struct {
401415
VoidCallback destruction_callback;
402416
} FlutterOpenGLFramebuffer;
403417

404-
typedef bool (*BoolCallback)(void* /* user data */);
405418
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
406419
typedef uint32_t (*UIntCallback)(void* /* user data */);
407420
typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,

flutter/shell/platform/tizen/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ template("embedder") {
9595
"channels/text_input_channel.cc",
9696
"channels/window_channel.cc",
9797
"external_texture_pixel_egl.cc",
98+
"external_texture_pixel_egl_impeller.cc",
9899
"external_texture_pixel_evas_gl.cc",
99100
"external_texture_surface_egl.cc",
101+
"external_texture_surface_egl_impeller.cc",
100102
"external_texture_surface_evas_gl.cc",
101103
"flutter_platform_node_delegate_tizen.cc",
102104
"flutter_project_bundle.cc",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2024 Samsung Electronics Co., Ltd. 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 "external_texture_pixel_egl_impeller.h"
6+
7+
#include <EGL/egl.h>
8+
#include <EGL/eglext.h>
9+
#include <GLES3/gl32.h>
10+
11+
#include "flutter/shell/platform/tizen/logger.h"
12+
13+
namespace flutter {
14+
15+
bool ExternalTexturePixelEGLImpeller::PopulateTexture(
16+
size_t width,
17+
size_t height,
18+
FlutterOpenGLTexture* opengl_texture) {
19+
if (!texture_callback_) {
20+
return false;
21+
}
22+
23+
const FlutterDesktopPixelBuffer* pixel_buffer =
24+
texture_callback_(width, height, user_data_);
25+
26+
if (!pixel_buffer || !pixel_buffer->buffer) {
27+
return false;
28+
}
29+
30+
width = pixel_buffer->width;
31+
height = pixel_buffer->height;
32+
33+
// Populate the texture object used by the engine.
34+
opengl_texture->impeller_texture_type =
35+
FlutterGLImpellerTextureType::kFlutterGLImpellerTexturePixelBuffer;
36+
opengl_texture->buffer = pixel_buffer->buffer;
37+
opengl_texture->buffer_size =
38+
size_t(pixel_buffer->width) * size_t(pixel_buffer->height) * 4;
39+
opengl_texture->destruction_callback = nullptr;
40+
opengl_texture->user_data = nullptr;
41+
opengl_texture->width = width;
42+
opengl_texture->height = height;
43+
return true;
44+
}
45+
46+
ExternalTexturePixelEGLImpeller::ExternalTexturePixelEGLImpeller(
47+
FlutterDesktopPixelBufferTextureCallback texture_callback,
48+
void* user_data)
49+
: ExternalTexture(),
50+
texture_callback_(texture_callback),
51+
user_data_(user_data) {}
52+
53+
} // namespace flutter
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2024 Samsung Electronics Co., Ltd. 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 EMBEDDER_EXTERNAL_TEXTURE_PIXEL_EGL_IMPELLER_H
6+
#define EMBEDDER_EXTERNAL_TEXTURE_PIXEL_EGL_IMPELLER_H
7+
8+
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
9+
#include "flutter/shell/platform/embedder/embedder.h"
10+
#include "flutter/shell/platform/tizen/external_texture.h"
11+
12+
namespace flutter {
13+
14+
class ExternalTexturePixelEGLImpeller : public ExternalTexture {
15+
public:
16+
ExternalTexturePixelEGLImpeller(
17+
FlutterDesktopPixelBufferTextureCallback texture_callback,
18+
void* user_data);
19+
20+
~ExternalTexturePixelEGLImpeller() = default;
21+
22+
bool PopulateTexture(size_t width,
23+
size_t height,
24+
FlutterOpenGLTexture* opengl_texture) override;
25+
26+
private:
27+
FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr;
28+
void* user_data_ = nullptr;
29+
};
30+
31+
} // namespace flutter
32+
33+
#endif // EMBEDDER_EXTERNAL_TEXTURE_PIXEL_EGL_IMPELLER_H
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
// Copyright 2024 Samsung Electronics Co., Ltd. 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 "external_texture_surface_egl_impeller.h"
6+
7+
#include <EGL/egl.h>
8+
#include <EGL/eglext.h>
9+
#include <GLES2/gl2.h>
10+
#include <GLES2/gl2ext.h>
11+
#include <GLES3/gl32.h>
12+
#include <tbm_bufmgr.h>
13+
#include <tbm_surface.h>
14+
#include <tbm_surface_internal.h>
15+
#include <type_traits>
16+
#ifndef EGL_DMA_BUF_PLANE3_FD_EXT
17+
#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
18+
#endif
19+
#ifndef EGL_DMA_BUF_PLANE3_OFFSET_EXT
20+
#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
21+
#endif
22+
#ifndef EGL_DMA_BUF_PLANE3_PITCH_EXT
23+
#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
24+
#endif
25+
26+
#include "flutter/shell/platform/tizen/logger.h"
27+
28+
namespace flutter {
29+
30+
ExternalTextureSurfaceEGLImpeller::ExternalTextureSurfaceEGLImpeller(
31+
ExternalTextureExtensionType gl_extension,
32+
FlutterDesktopGpuSurfaceTextureCallback texture_callback,
33+
void* user_data)
34+
: ExternalTexture(gl_extension),
35+
texture_callback_(texture_callback),
36+
user_data_(user_data) {}
37+
38+
ExternalTextureSurfaceEGLImpeller::~ExternalTextureSurfaceEGLImpeller() {
39+
ReleaseImage();
40+
}
41+
42+
bool ExternalTextureSurfaceEGLImpeller::PopulateTexture(
43+
size_t width,
44+
size_t height,
45+
FlutterOpenGLTexture* opengl_texture) {
46+
if (!texture_callback_) {
47+
return false;
48+
}
49+
const FlutterDesktopGpuSurfaceDescriptor* gpu_surface =
50+
texture_callback_(width, height, user_data_);
51+
if (!gpu_surface) {
52+
FT_LOG(Info) << "gpu_surface is null for texture ID: " << texture_id_;
53+
return false;
54+
}
55+
56+
if (!CreateOrUpdateEglImage(gpu_surface)) {
57+
FT_LOG(Info) << "CreateOrUpdateEglImage fail for texture ID: "
58+
<< texture_id_;
59+
return false;
60+
}
61+
62+
opengl_texture->impeller_texture_type =
63+
FlutterGLImpellerTextureType::kFlutterGLImpellerTextureGpuSurface;
64+
opengl_texture->bind_callback = OnBindCallback;
65+
opengl_texture->destruction_callback = nullptr;
66+
opengl_texture->user_data = this;
67+
opengl_texture->width = width;
68+
opengl_texture->height = height;
69+
return true;
70+
}
71+
72+
bool ExternalTextureSurfaceEGLImpeller::CreateOrUpdateEglImage(
73+
const FlutterDesktopGpuSurfaceDescriptor* descriptor) {
74+
if (descriptor == nullptr || descriptor->handle == nullptr) {
75+
ReleaseImage();
76+
return false;
77+
}
78+
void* handle = descriptor->handle;
79+
if (handle != last_surface_handle_) {
80+
ReleaseImage();
81+
82+
const tbm_surface_h tbm_surface =
83+
reinterpret_cast<tbm_surface_h>(descriptor->handle);
84+
85+
tbm_surface_info_s info;
86+
if (tbm_surface_get_info(tbm_surface, &info) != TBM_SURFACE_ERROR_NONE) {
87+
if (descriptor->release_callback) {
88+
descriptor->release_callback(descriptor->release_context);
89+
}
90+
return false;
91+
}
92+
93+
PFNEGLCREATEIMAGEKHRPROC n_eglCreateImageKHR =
94+
reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(
95+
eglGetProcAddress("eglCreateImageKHR"));
96+
97+
if (state_->gl_extension == ExternalTextureExtensionType::kNativeSurface) {
98+
const EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE,
99+
EGL_NONE};
100+
egl_src_image_ =
101+
n_eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
102+
EGL_NATIVE_SURFACE_TIZEN, tbm_surface, attribs);
103+
} else if (state_->gl_extension ==
104+
ExternalTextureExtensionType::kDmaBuffer) {
105+
EGLint attribs[50];
106+
int atti = 0;
107+
int plane_fd_ext[4] = {
108+
EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE1_FD_EXT,
109+
EGL_DMA_BUF_PLANE2_FD_EXT, EGL_DMA_BUF_PLANE3_FD_EXT};
110+
int plane_offset_ext[4] = {
111+
EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE1_OFFSET_EXT,
112+
EGL_DMA_BUF_PLANE2_OFFSET_EXT, EGL_DMA_BUF_PLANE3_OFFSET_EXT};
113+
int plane_pitch_ext[4] = {
114+
EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE1_PITCH_EXT,
115+
EGL_DMA_BUF_PLANE2_PITCH_EXT, EGL_DMA_BUF_PLANE3_PITCH_EXT};
116+
117+
attribs[atti++] = EGL_WIDTH;
118+
attribs[atti++] = info.width;
119+
attribs[atti++] = EGL_HEIGHT;
120+
attribs[atti++] = info.height;
121+
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
122+
attribs[atti++] = info.format;
123+
124+
int num_planes = tbm_surface_internal_get_num_planes(info.format);
125+
for (int i = 0; i < num_planes; i++) {
126+
int bo_idx = tbm_surface_internal_get_plane_bo_idx(tbm_surface, i);
127+
tbm_bo tbo = tbm_surface_internal_get_bo(tbm_surface, bo_idx);
128+
attribs[atti++] = plane_fd_ext[i];
129+
attribs[atti++] = static_cast<int>(reinterpret_cast<size_t>(
130+
tbm_bo_get_handle(tbo, TBM_DEVICE_3D).ptr));
131+
attribs[atti++] = plane_offset_ext[i];
132+
attribs[atti++] = info.planes[i].offset;
133+
attribs[atti++] = plane_pitch_ext[i];
134+
attribs[atti++] = info.planes[i].stride;
135+
}
136+
attribs[atti++] = EGL_NONE;
137+
egl_src_image_ =
138+
n_eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
139+
EGL_LINUX_DMA_BUF_EXT, nullptr, attribs);
140+
}
141+
if (!egl_src_image_) {
142+
if (state_->gl_extension != ExternalTextureExtensionType::kNone) {
143+
FT_LOG(Error) << "eglCreateImageKHR failed with an error "
144+
<< eglGetError() << " for texture ID: " << texture_id_;
145+
} else {
146+
FT_LOG(Error) << "Either EGL_TIZEN_image_native_surface or "
147+
"EGL_EXT_image_dma_buf_import shoule be supported.";
148+
}
149+
if (descriptor->release_callback) {
150+
descriptor->release_callback(descriptor->release_context);
151+
}
152+
return false;
153+
}
154+
last_surface_handle_ = handle;
155+
}
156+
if (descriptor->release_callback) {
157+
descriptor->release_callback(descriptor->release_context);
158+
}
159+
return true;
160+
}
161+
162+
void ExternalTextureSurfaceEGLImpeller::ReleaseImage() {
163+
if (egl_src_image_) {
164+
PFNEGLDESTROYIMAGEKHRPROC n_eglDestroyImageKHR =
165+
reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(
166+
eglGetProcAddress("eglDestroyImageKHR"));
167+
n_eglDestroyImageKHR(eglGetCurrentDisplay(), egl_src_image_);
168+
egl_src_image_ = nullptr;
169+
}
170+
}
171+
172+
bool ExternalTextureSurfaceEGLImpeller::OnBindCallback(void* user_data) {
173+
ExternalTextureSurfaceEGLImpeller* self =
174+
static_cast<ExternalTextureSurfaceEGLImpeller*>(user_data);
175+
return self->OnBind();
176+
}
177+
178+
bool ExternalTextureSurfaceEGLImpeller::OnBind() {
179+
if (!egl_src_image_) {
180+
return false;
181+
}
182+
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES =
183+
reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(
184+
eglGetProcAddress("glEGLImageTargetTexture2DOES"));
185+
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_src_image_);
186+
return true;
187+
}
188+
189+
} // namespace flutter
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2024 Samsung Electronics Co., Ltd. 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 EMBEDDER_EXTERNAL_TEXTURE_SURFACE_EGL_IMPELLER_H_
6+
#define EMBEDDER_EXTERNAL_TEXTURE_SURFACE_EGL_IMPELLER_H_
7+
8+
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
9+
#include "flutter/shell/platform/embedder/embedder.h"
10+
#include "flutter/shell/platform/tizen/external_texture.h"
11+
12+
#include <EGL/egl.h>
13+
#include <EGL/eglext.h>
14+
15+
namespace flutter {
16+
17+
class ExternalTextureSurfaceEGLImpeller : public ExternalTexture {
18+
public:
19+
ExternalTextureSurfaceEGLImpeller(
20+
ExternalTextureExtensionType gl_extension,
21+
FlutterDesktopGpuSurfaceTextureCallback texture_callback,
22+
void* user_data);
23+
24+
virtual ~ExternalTextureSurfaceEGLImpeller();
25+
26+
// Accepts texture buffer copy request from the Flutter engine.
27+
// When the user side marks the texture_id as available, the Flutter engine
28+
// will callback to this method and ask to populate the |opengl_texture|
29+
// object, such as the texture type and the format of the pixel buffer and the
30+
// texture object.
31+
//
32+
// Returns true on success, false on failure.
33+
bool PopulateTexture(size_t width,
34+
size_t height,
35+
FlutterOpenGLTexture* opengl_texture) override;
36+
37+
private:
38+
static bool OnBindCallback(void* user_data);
39+
bool CreateOrUpdateEglImage(
40+
const FlutterDesktopGpuSurfaceDescriptor* descriptor);
41+
void ReleaseImage();
42+
bool OnBind();
43+
FlutterDesktopGpuSurfaceTextureCallback texture_callback_ = nullptr;
44+
void* user_data_ = nullptr;
45+
EGLImageKHR egl_src_image_ = nullptr;
46+
void* last_surface_handle_ = nullptr;
47+
};
48+
49+
} // namespace flutter
50+
51+
#endif // EMBEDDER_EXTERNAL_TEXTURE_SURFACE_EGL_IMPELLER_H_

flutter/shell/platform/tizen/flutter_tizen_engine.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ bool FlutterTizenEngine::RunEngine() {
240240
internal_plugin_registrar_->messenger());
241241

242242
if (IsHeaded()) {
243-
texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(this);
243+
texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(
244+
this, project_->HasArgument("--enable-impeller"));
244245
keyboard_channel_ = std::make_unique<KeyboardChannel>(
245246
internal_plugin_registrar_->messenger(),
246247
[this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback,

0 commit comments

Comments
 (0)