diff --git a/flutter/shell/platform/embedder/embedder.h b/flutter/shell/platform/embedder/embedder.h index d26e221..117aa71 100644 --- a/flutter/shell/platform/embedder/embedder.h +++ b/flutter/shell/platform/embedder/embedder.h @@ -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 @@ -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). @@ -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 @@ -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 */, diff --git a/flutter/shell/platform/tizen/BUILD.gn b/flutter/shell/platform/tizen/BUILD.gn index 5515509..1961ff9 100644 --- a/flutter/shell/platform/tizen/BUILD.gn +++ b/flutter/shell/platform/tizen/BUILD.gn @@ -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", diff --git a/flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.cc b/flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.cc new file mode 100755 index 0000000..7240793 --- /dev/null +++ b/flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.cc @@ -0,0 +1,53 @@ +// 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. + +#include "external_texture_pixel_egl_impeller.h" + +#include +#include +#include + +#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 diff --git a/flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.h b/flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.h new file mode 100755 index 0000000..ebaad4e --- /dev/null +++ b/flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.h @@ -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 diff --git a/flutter/shell/platform/tizen/external_texture_surface_egl_impeller.cc b/flutter/shell/platform/tizen/external_texture_surface_egl_impeller.cc new file mode 100755 index 0000000..3106ab2 --- /dev/null +++ b/flutter/shell/platform/tizen/external_texture_surface_egl_impeller.cc @@ -0,0 +1,189 @@ +// 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. + +#include "external_texture_surface_egl_impeller.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(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( + 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(reinterpret_cast( + 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( + eglGetProcAddress("eglDestroyImageKHR")); + n_eglDestroyImageKHR(eglGetCurrentDisplay(), egl_src_image_); + egl_src_image_ = nullptr; + } +} + +bool ExternalTextureSurfaceEGLImpeller::OnBindCallback(void* user_data) { + ExternalTextureSurfaceEGLImpeller* self = + static_cast(user_data); + return self->OnBind(); +} + +bool ExternalTextureSurfaceEGLImpeller::OnBind() { + if (!egl_src_image_) { + return false; + } + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = + reinterpret_cast( + eglGetProcAddress("glEGLImageTargetTexture2DOES")); + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_src_image_); + return true; +} + +} // namespace flutter diff --git a/flutter/shell/platform/tizen/external_texture_surface_egl_impeller.h b/flutter/shell/platform/tizen/external_texture_surface_egl_impeller.h new file mode 100755 index 0000000..d957000 --- /dev/null +++ b/flutter/shell/platform/tizen/external_texture_surface_egl_impeller.h @@ -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 +#include + +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_ diff --git a/flutter/shell/platform/tizen/flutter_tizen_engine.cc b/flutter/shell/platform/tizen/flutter_tizen_engine.cc index e2708a4..9db350f 100644 --- a/flutter/shell/platform/tizen/flutter_tizen_engine.cc +++ b/flutter/shell/platform/tizen/flutter_tizen_engine.cc @@ -240,7 +240,8 @@ bool FlutterTizenEngine::RunEngine() { internal_plugin_registrar_->messenger()); if (IsHeaded()) { - texture_registrar_ = std::make_unique(this); + texture_registrar_ = std::make_unique( + this, project_->HasArgument("--enable-impeller")); keyboard_channel_ = std::make_unique( internal_plugin_registrar_->messenger(), [this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback, diff --git a/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.cc b/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.cc index 28eb976..a3b4181 100644 --- a/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.cc +++ b/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.cc @@ -8,8 +8,10 @@ #include #include "flutter/shell/platform/tizen/external_texture_pixel_egl.h" +#include "flutter/shell/platform/tizen/external_texture_pixel_egl_impeller.h" #include "flutter/shell/platform/tizen/external_texture_pixel_evas_gl.h" #include "flutter/shell/platform/tizen/external_texture_surface_egl.h" +#include "flutter/shell/platform/tizen/external_texture_surface_egl_impeller.h" #include "flutter/shell/platform/tizen/external_texture_surface_evas_gl.h" #include "flutter/shell/platform/tizen/flutter_tizen_engine.h" #include "flutter/shell/platform/tizen/logger.h" @@ -18,8 +20,9 @@ namespace flutter { FlutterTizenTextureRegistrar::FlutterTizenTextureRegistrar( - FlutterTizenEngine* engine) - : engine_(engine) {} + FlutterTizenEngine* engine, + bool enable_impeller) + : engine_(engine), enable_impeller_(enable_impeller) {} int64_t FlutterTizenTextureRegistrar::RegisterTexture( const FlutterDesktopTextureInfo* texture_info) { @@ -108,9 +111,15 @@ FlutterTizenTextureRegistrar::CreateExternalTexture( texture_info->pixel_buffer_config.callback, texture_info->pixel_buffer_config.user_data); } - return std::make_unique( - texture_info->pixel_buffer_config.callback, - texture_info->pixel_buffer_config.user_data); + if (enable_impeller_) { + return std::make_unique( + texture_info->pixel_buffer_config.callback, + texture_info->pixel_buffer_config.user_data); + } else { + return std::make_unique( + texture_info->pixel_buffer_config.callback, + texture_info->pixel_buffer_config.user_data); + } case kFlutterDesktopGpuSurfaceTexture: ExternalTextureExtensionType gl_extension = ExternalTextureExtensionType::kNone; @@ -127,9 +136,15 @@ FlutterTizenTextureRegistrar::CreateExternalTexture( gl_extension, texture_info->gpu_surface_config.callback, texture_info->gpu_surface_config.user_data); } - return std::make_unique( - gl_extension, texture_info->gpu_surface_config.callback, - texture_info->gpu_surface_config.user_data); + if (enable_impeller_) { + return std::make_unique( + gl_extension, texture_info->gpu_surface_config.callback, + texture_info->gpu_surface_config.user_data); + } else { + return std::make_unique( + gl_extension, texture_info->gpu_surface_config.callback, + texture_info->gpu_surface_config.user_data); + } } } diff --git a/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.h b/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.h index 4b7d1b3..a56976e 100644 --- a/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.h +++ b/flutter/shell/platform/tizen/flutter_tizen_texture_registrar.h @@ -20,7 +20,8 @@ class FlutterTizenEngine; // Thread safety: All member methods are thread safe. class FlutterTizenTextureRegistrar { public: - explicit FlutterTizenTextureRegistrar(FlutterTizenEngine* engine); + explicit FlutterTizenTextureRegistrar(FlutterTizenEngine* engine, + bool enable_impeller); // Registers a texture described by the given |texture_info| object. // @@ -56,6 +57,7 @@ class FlutterTizenTextureRegistrar { // All registered textures, keyed by their IDs. std::unordered_map> textures_; std::mutex map_mutex_; + bool enable_impeller_ = false; }; } // namespace flutter diff --git a/flutter/shell/platform/tizen/flutter_tizen_texture_registrar_unittests.cc b/flutter/shell/platform/tizen/flutter_tizen_texture_registrar_unittests.cc index f757c4c..0f9d156 100644 --- a/flutter/shell/platform/tizen/flutter_tizen_texture_registrar_unittests.cc +++ b/flutter/shell/platform/tizen/flutter_tizen_texture_registrar_unittests.cc @@ -43,7 +43,7 @@ class FlutterTizenTextureRegistrarTest : public ::testing::Test { }; TEST_F(FlutterTizenTextureRegistrarTest, CreateDestroy) { - FlutterTizenTextureRegistrar registrar(engine_); + FlutterTizenTextureRegistrar registrar(engine_, false); EXPECT_TRUE(true); } @@ -51,7 +51,7 @@ TEST_F(FlutterTizenTextureRegistrarTest, CreateDestroy) { TEST_F(FlutterTizenTextureRegistrarTest, RegisterUnregisterTexture) { EngineModifier modifier(engine_); - FlutterTizenTextureRegistrar registrar(engine_); + FlutterTizenTextureRegistrar registrar(engine_, false); FlutterDesktopTextureInfo texture_info = {}; texture_info.type = kFlutterDesktopGpuSurfaceTexture; @@ -105,7 +105,7 @@ TEST_F(FlutterTizenTextureRegistrarTest, RegisterUnregisterTexture) { TEST_F(FlutterTizenTextureRegistrarTest, RegisterUnknownTextureType) { EngineModifier modifier(engine_); - FlutterTizenTextureRegistrar registrar(engine_); + FlutterTizenTextureRegistrar registrar(engine_, false); FlutterDesktopTextureInfo texture_info = {}; texture_info.type = static_cast(1234); @@ -116,7 +116,7 @@ TEST_F(FlutterTizenTextureRegistrarTest, RegisterUnknownTextureType) { } TEST_F(FlutterTizenTextureRegistrarTest, PopulateInvalidTexture) { - FlutterTizenTextureRegistrar registrar(engine_); + FlutterTizenTextureRegistrar registrar(engine_, false); bool result = registrar.PopulateTexture(1, 640, 480, nullptr); EXPECT_FALSE(result);