Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support EmbedderExternalTextureGL for impeller #69

Merged
merged 6 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion flutter/shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ typedef struct {
} FlutterTransformation;

typedef void (*VoidCallback)(void* /* user data */);
typedef bool (*BoolCallback)(void* /* user data */);

typedef enum {
/// Specifies an OpenGL texture target type. Textures are specified using
Expand Down Expand Up @@ -361,6 +362,11 @@ typedef enum {
kFlutterSoftwarePixelFormatNative32,
} FlutterSoftwarePixelFormat;

typedef enum {
kFlutterGLImpellerTexturePixelBuffer,
kFlutterGLImpellerTextureGpuSurface,
} FlutterGLImpellerTextureType;

typedef struct {
/// Target texture of the active texture unit (example GL_TEXTURE_2D or
/// GL_TEXTURE_RECTANGLE).
Expand All @@ -369,6 +375,14 @@ typedef struct {
uint32_t name;
/// The texture format (example GL_RGBA8).
uint32_t format;
/// The pixel data buffer.
const uint8_t* buffer;
/// The size of pixel buffer.
size_t buffer_size;
/// Callback invoked that the gpu surface texture start binding.
BoolCallback bind_callback;
/// The type of the texture.
FlutterGLImpellerTextureType impeller_texture_type;
/// User data to be returned on the invocation of the destruction callback.
void* user_data;
/// Callback invoked (on an engine managed thread) that asks the embedder to
Expand Down Expand Up @@ -401,7 +415,6 @@ typedef struct {
VoidCallback destruction_callback;
} FlutterOpenGLFramebuffer;

typedef bool (*BoolCallback)(void* /* user data */);
typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
typedef uint32_t (*UIntCallback)(void* /* user data */);
typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,
Expand Down
2 changes: 2 additions & 0 deletions flutter/shell/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ template("embedder") {
"channels/text_input_channel.cc",
"channels/window_channel.cc",
"external_texture_pixel_egl.cc",
"external_texture_pixel_egl_impeller.cc",
"external_texture_pixel_evas_gl.cc",
"external_texture_surface_egl.cc",
"external_texture_surface_egl_impeller.cc",
"external_texture_surface_evas_gl.cc",
"flutter_platform_node_delegate_tizen.cc",
"flutter_project_bundle.cc",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2020 Samsung Electronics Co., Ltd. All rights reserved.
JSUYA marked this conversation as resolved.
Show resolved Hide resolved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "external_texture_pixel_egl_impeller.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl32.h>

#include "flutter/shell/platform/tizen/logger.h"

namespace flutter {

bool ExternalTexturePixelEGLImpeller::PopulateTexture(
size_t width,
size_t height,
FlutterOpenGLTexture* opengl_texture) {
if (!texture_callback_) {
return false;
}

const FlutterDesktopPixelBuffer* pixel_buffer =
texture_callback_(width, height, user_data_);

if (!pixel_buffer || !pixel_buffer->buffer) {
return false;
}

width = pixel_buffer->width;
height = pixel_buffer->height;

// Populate the texture object used by the engine.
opengl_texture->impeller_texture_type =
FlutterGLImpellerTextureType::kFlutterGLImpellerTexturePixelBuffer;
opengl_texture->buffer = pixel_buffer->buffer;
opengl_texture->buffer_size =
size_t(pixel_buffer->width) * size_t(pixel_buffer->height) * 4;
opengl_texture->destruction_callback = nullptr;
opengl_texture->user_data = nullptr;
opengl_texture->width = width;
opengl_texture->height = height;
return true;
}

ExternalTexturePixelEGLImpeller::ExternalTexturePixelEGLImpeller(
FlutterDesktopPixelBufferTextureCallback texture_callback,
void* user_data)
: ExternalTexture(),
texture_callback_(texture_callback),
user_data_(user_data) {}

} // namespace flutter
33 changes: 33 additions & 0 deletions flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 Samsung Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EMBEDDER_EXTERNAL_TEXTURE_PIXEL_EGL_IMPELLER_H
#define EMBEDDER_EXTERNAL_TEXTURE_PIXEL_EGL_IMPELLER_H

#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/tizen/external_texture.h"

namespace flutter {

class ExternalTexturePixelEGLImpeller : public ExternalTexture {
public:
ExternalTexturePixelEGLImpeller(
FlutterDesktopPixelBufferTextureCallback texture_callback,
void* user_data);

~ExternalTexturePixelEGLImpeller() = default;

bool PopulateTexture(size_t width,
size_t height,
FlutterOpenGLTexture* opengl_texture) override;

private:
FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr;
void* user_data_ = nullptr;
};

} // namespace flutter

#endif // EMBEDDER_EXTERNAL_TEXTURE_PIXEL_EGL_IMPELLER_H
189 changes: 189 additions & 0 deletions flutter/shell/platform/tizen/external_texture_surface_egl_impeller.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Copyright 2020 Samsung Electronics Co., Ltd. All rights reserved.
JSUYA marked this conversation as resolved.
Show resolved Hide resolved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "external_texture_surface_egl_impeller.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl32.h>
#include <tbm_bufmgr.h>
#include <tbm_surface.h>
#include <tbm_surface_internal.h>
#include <type_traits>
#ifndef EGL_DMA_BUF_PLANE3_FD_EXT
#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
#endif
#ifndef EGL_DMA_BUF_PLANE3_OFFSET_EXT
#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
#endif
#ifndef EGL_DMA_BUF_PLANE3_PITCH_EXT
#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
#endif

#include "flutter/shell/platform/tizen/logger.h"

namespace flutter {

ExternalTextureSurfaceEGLImpeller::ExternalTextureSurfaceEGLImpeller(
ExternalTextureExtensionType gl_extension,
FlutterDesktopGpuSurfaceTextureCallback texture_callback,
void* user_data)
: ExternalTexture(gl_extension),
texture_callback_(texture_callback),
user_data_(user_data) {}

ExternalTextureSurfaceEGLImpeller::~ExternalTextureSurfaceEGLImpeller() {
ReleaseImage();
}

bool ExternalTextureSurfaceEGLImpeller::PopulateTexture(
size_t width,
size_t height,
FlutterOpenGLTexture* opengl_texture) {
if (!texture_callback_) {
return false;
}
const FlutterDesktopGpuSurfaceDescriptor* gpu_surface =
texture_callback_(width, height, user_data_);
if (!gpu_surface) {
FT_LOG(Info) << "gpu_surface is null for texture ID: " << texture_id_;
return false;
}

if (!CreateOrUpdateEglImage(gpu_surface)) {
FT_LOG(Info) << "CreateOrUpdateEglImage fail for texture ID: "
<< texture_id_;
return false;
}

opengl_texture->impeller_texture_type =
FlutterGLImpellerTextureType::kFlutterGLImpellerTextureGpuSurface;
opengl_texture->bind_callback = OnBindCallback;
opengl_texture->destruction_callback = nullptr;
opengl_texture->user_data = this;
opengl_texture->width = width;
opengl_texture->height = height;
return true;
}

bool ExternalTextureSurfaceEGLImpeller::CreateOrUpdateEglImage(
const FlutterDesktopGpuSurfaceDescriptor* descriptor) {
if (descriptor == nullptr || descriptor->handle == nullptr) {
ReleaseImage();
return false;
}
void* handle = descriptor->handle;
if (handle != last_surface_handle_) {
ReleaseImage();

const tbm_surface_h tbm_surface =
reinterpret_cast<tbm_surface_h>(descriptor->handle);

tbm_surface_info_s info;
if (tbm_surface_get_info(tbm_surface, &info) != TBM_SURFACE_ERROR_NONE) {
if (descriptor->release_callback) {
descriptor->release_callback(descriptor->release_context);
}
return false;
}

PFNEGLCREATEIMAGEKHRPROC n_eglCreateImageKHR =
reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(
eglGetProcAddress("eglCreateImageKHR"));

if (state_->gl_extension == ExternalTextureExtensionType::kNativeSurface) {
const EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE,
EGL_NONE};
egl_src_image_ =
n_eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
EGL_NATIVE_SURFACE_TIZEN, tbm_surface, attribs);
} else if (state_->gl_extension ==
ExternalTextureExtensionType::kDmaBuffer) {
EGLint attribs[50];
int atti = 0;
int plane_fd_ext[4] = {
EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE1_FD_EXT,
EGL_DMA_BUF_PLANE2_FD_EXT, EGL_DMA_BUF_PLANE3_FD_EXT};
int plane_offset_ext[4] = {
EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE1_OFFSET_EXT,
EGL_DMA_BUF_PLANE2_OFFSET_EXT, EGL_DMA_BUF_PLANE3_OFFSET_EXT};
int plane_pitch_ext[4] = {
EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE1_PITCH_EXT,
EGL_DMA_BUF_PLANE2_PITCH_EXT, EGL_DMA_BUF_PLANE3_PITCH_EXT};

attribs[atti++] = EGL_WIDTH;
attribs[atti++] = info.width;
attribs[atti++] = EGL_HEIGHT;
attribs[atti++] = info.height;
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[atti++] = info.format;

int num_planes = tbm_surface_internal_get_num_planes(info.format);
for (int i = 0; i < num_planes; i++) {
int bo_idx = tbm_surface_internal_get_plane_bo_idx(tbm_surface, i);
tbm_bo tbo = tbm_surface_internal_get_bo(tbm_surface, bo_idx);
attribs[atti++] = plane_fd_ext[i];
attribs[atti++] = static_cast<int>(reinterpret_cast<size_t>(
tbm_bo_get_handle(tbo, TBM_DEVICE_3D).ptr));
attribs[atti++] = plane_offset_ext[i];
attribs[atti++] = info.planes[i].offset;
attribs[atti++] = plane_pitch_ext[i];
attribs[atti++] = info.planes[i].stride;
}
attribs[atti++] = EGL_NONE;
egl_src_image_ =
n_eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, nullptr, attribs);
}
if (!egl_src_image_) {
if (state_->gl_extension != ExternalTextureExtensionType::kNone) {
FT_LOG(Error) << "eglCreateImageKHR failed with an error "
<< eglGetError() << " for texture ID: " << texture_id_;
} else {
FT_LOG(Error) << "Either EGL_TIZEN_image_native_surface or "
"EGL_EXT_image_dma_buf_import shoule be supported.";
}
if (descriptor->release_callback) {
descriptor->release_callback(descriptor->release_context);
}
return false;
}
last_surface_handle_ = handle;
}
if (descriptor->release_callback) {
descriptor->release_callback(descriptor->release_context);
}
return true;
}

void ExternalTextureSurfaceEGLImpeller::ReleaseImage() {
if (egl_src_image_) {
PFNEGLDESTROYIMAGEKHRPROC n_eglDestroyImageKHR =
reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(
eglGetProcAddress("eglDestroyImageKHR"));
n_eglDestroyImageKHR(eglGetCurrentDisplay(), egl_src_image_);
egl_src_image_ = nullptr;
}
}

bool ExternalTextureSurfaceEGLImpeller::OnBindCallback(void* user_data) {
ExternalTextureSurfaceEGLImpeller* self =
static_cast<ExternalTextureSurfaceEGLImpeller*>(user_data);
return self->OnBind();
}

bool ExternalTextureSurfaceEGLImpeller::OnBind() {
if (!egl_src_image_) {
return false;
}
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES =
reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(
eglGetProcAddress("glEGLImageTargetTexture2DOES"));
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_src_image_);
return true;
}

} // namespace flutter
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2024 Samsung Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EMBEDDER_EXTERNAL_TEXTURE_SURFACE_EGL_IMPELLER_H_
#define EMBEDDER_EXTERNAL_TEXTURE_SURFACE_EGL_IMPELLER_H_

#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/tizen/external_texture.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>

namespace flutter {

class ExternalTextureSurfaceEGLImpeller : public ExternalTexture {
public:
ExternalTextureSurfaceEGLImpeller(
ExternalTextureExtensionType gl_extension,
FlutterDesktopGpuSurfaceTextureCallback texture_callback,
void* user_data);

virtual ~ExternalTextureSurfaceEGLImpeller();

// Accepts texture buffer copy request from the Flutter engine.
// When the user side marks the texture_id as available, the Flutter engine
// will callback to this method and ask to populate the |opengl_texture|
// object, such as the texture type and the format of the pixel buffer and the
// texture object.
//
// Returns true on success, false on failure.
bool PopulateTexture(size_t width,
size_t height,
FlutterOpenGLTexture* opengl_texture) override;

private:
static bool OnBindCallback(void* user_data);
bool CreateOrUpdateEglImage(
const FlutterDesktopGpuSurfaceDescriptor* descriptor);
void ReleaseImage();
bool OnBind();
FlutterDesktopGpuSurfaceTextureCallback texture_callback_ = nullptr;
void* user_data_ = nullptr;
EGLImageKHR egl_src_image_ = nullptr;
void* last_surface_handle_ = nullptr;
};

} // namespace flutter

#endif // EMBEDDER_EXTERNAL_TEXTURE_SURFACE_EGL_IMPELLER_H_
3 changes: 2 additions & 1 deletion flutter/shell/platform/tizen/flutter_tizen_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ bool FlutterTizenEngine::RunEngine() {
internal_plugin_registrar_->messenger());

if (IsHeaded()) {
texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(this);
texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(
this, project_->HasArgument("--enable-impeller"));
keyboard_channel_ = std::make_unique<KeyboardChannel>(
internal_plugin_registrar_->messenger(),
[this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback,
Expand Down
Loading