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

Add support EGLImage-based texture #327

Merged
merged 1 commit into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Hidenori Matsubayashi ([email protected])
Andrea Daoud ([email protected])
Valentin Hăloiu ([email protected])
FlafyDev <[email protected]>
Makoto Sato ([email protected])
1 change: 1 addition & 0 deletions cmake/build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ set(ELINUX_COMMON_SRC
"src/flutter/shell/platform/linux_embedded/system_utils.cc"
"src/flutter/shell/platform/linux_embedded/logger.cc"
"src/flutter/shell/platform/linux_embedded/external_texture_pixelbuffer.cc"
"src/flutter/shell/platform/linux_embedded/external_texture_egl_image.cc"
"src/flutter/shell/platform/linux_embedded/vsync_waiter.cc"
"src/flutter/shell/platform/linux_embedded/flutter_elinux_texture_registrar.cc"
"src/flutter/shell/platform/linux_embedded/plugins/keyboard_glfw_util.cc"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) {
auto texture = static_cast<GpuSurfaceTexture*>(user_data);
return texture->ObtainDescriptor(width, height);
};
} else if (auto egl_image_texture = std::get_if<EGLImageTexture>(texture)) {
info.type = kFlutterDesktopEGLImageTexture;
info.egl_image_config.user_data = egl_image_texture;
info.egl_image_config.callback =
[](size_t width, size_t height, void* egl_display, void* egl_context,
void* user_data) -> const FlutterDesktopEGLImage* {
auto texture = static_cast<EGLImageTexture*>(user_data);
return texture->GetEGLImage(width, height, egl_display, egl_context);
};
} else {
std::cerr << "Attempting to register unknown texture variant." << std::endl;
return -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,38 @@ class PixelBufferTexture {
const CopyBufferCallback copy_buffer_callback_;
};

// A EGLImage texture.
class EGLImageTexture {
public:
// A callback used for retrieving pixel buffers.
typedef std::function<const FlutterDesktopEGLImage*(size_t width,
size_t height,
void* egl_display,
void* egl_context)>
GetEGLImageCallback;

// Creates a EGLImage texture that uses the provided |get_egl_image_cb| to
// retrieve the EGLImage.
// As the callback is usually invoked from the render thread, the callee must
// take care of proper synchronization. It also needs to be ensured that the
// returned buffer isn't released prior to unregistering this texture.
explicit EGLImageTexture(GetEGLImageCallback get_egl_image_callback)
: get_egl_image_callback_(get_egl_image_callback) {}

// Returns the callback-provided FlutterDesktopEGLImage.
// The intended surface size is specified by |width| and
// |height|.
const FlutterDesktopEGLImage* GetEGLImage(size_t width,
size_t height,
void* egl_display,
void* egl_context) const {
return get_egl_image_callback_(width, height, egl_display, egl_context);
}

private:
const GetEGLImageCallback get_egl_image_callback_;
};

// A GPU surface-based texture.
class GpuSurfaceTexture {
public:
Expand Down Expand Up @@ -75,7 +107,7 @@ class GpuSurfaceTexture {
// The available texture variants.
// Only PixelBufferTexture is currently implemented.
// Other variants are expected to be added in the future.
typedef std::variant<PixelBufferTexture, GpuSurfaceTexture> TextureVariant;
typedef std::variant<PixelBufferTexture, GpuSurfaceTexture, EGLImageTexture> TextureVariant;

// An object keeping track of external textures.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ typedef enum {
// A Pixel buffer-based texture.
kFlutterDesktopPixelBufferTexture,
// A platform-specific GPU surface-backed texture.
kFlutterDesktopGpuSurfaceTexture
kFlutterDesktopGpuSurfaceTexture,
// An EGLImage-based texture
kFlutterDesktopEGLImageTexture
} FlutterDesktopTextureType;

// Supported GPU surface types.
Expand Down Expand Up @@ -66,6 +68,20 @@ typedef struct {
void* release_context;
} FlutterDesktopPixelBuffer;

// An EGLImage object.
typedef struct {
// The EGLImage object.(opaque)
const void* egl_image;
// Width of the EGLImage.
size_t width;
// Height of the EGLImage.
size_t height;
// An optional callback that gets invoked when the |egl_image| can be released.
void (*release_callback)(void* release_context);
// Opaque data passed to |release_callback|.
void* release_context;
} FlutterDesktopEGLImage;

// A GPU surface descriptor.
typedef struct {
// The size of this struct. Must be
Expand Down Expand Up @@ -126,6 +142,13 @@ typedef const FlutterDesktopGpuSurfaceDescriptor* (
size_t height,
void* user_data);

typedef const FlutterDesktopEGLImage* (
*FlutterDesktopEGLImageTextureCallback)(size_t width,
size_t height,
void* egl_display,
void* egl_context,
void* user_data);

// An object used to configure pixel buffer textures.
typedef struct {
// The callback used by the engine to copy the pixel buffer object.
Expand All @@ -148,11 +171,20 @@ typedef struct {
void* user_data;
} FlutterDesktopGpuSurfaceTextureConfig;

// An object used to configure EGLImage textures.
typedef struct {
// The callback used by the engine to get the EGLImage object.
FlutterDesktopEGLImageTextureCallback callback;
// Opaque data that will get passed to the provided |callback|.
void* user_data;
} FlutterDesktopEGLImageTextureConfig;

typedef struct {
FlutterDesktopTextureType type;
union {
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config;
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config;
FlutterDesktopEGLImageTextureConfig egl_image_config;
};
} FlutterDesktopTextureInfo;

Expand Down
3 changes: 3 additions & 0 deletions src/flutter/shell/platform/linux_embedded/external_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ typedef void (*glTexImage2DProc)(GLenum target,
GLenum format,
GLenum type,
const void* data);
typedef void (*glEGLImageTargetTexture2DOESProc)(GLenum target,
GLeglImageOES image);

// A struct containing pointers to resolved gl* functions.
struct GlProcs {
Expand All @@ -37,6 +39,7 @@ struct GlProcs {
glBindTextureProc glBindTexture;
glTexParameteriProc glTexParameteri;
glTexImage2DProc glTexImage2D;
glEGLImageTargetTexture2DOESProc glEGLImageTargetTexture2DOES;
bool valid;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/linux_embedded/external_texture_egl_image.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>

namespace flutter {

struct ExternalTextureEGLImageState {
GLuint gl_texture = 0;
};

ExternalTextureEGLImage::ExternalTextureEGLImage(
FlutterDesktopEGLImageTextureCallback texture_callback,
void* user_data,
const GlProcs& gl_procs)
: state_(std::make_unique<ExternalTextureEGLImageState>()),
texture_callback_(texture_callback),
user_data_(user_data),
gl_(gl_procs) {}

ExternalTextureEGLImage::~ExternalTextureEGLImage() {
if (state_->gl_texture != 0) {
gl_.glDeleteTextures(1, &state_->gl_texture);
}
}

bool ExternalTextureEGLImage::PopulateTexture(
size_t width,
size_t height,
FlutterOpenGLTexture* opengl_texture) {
if (!GetEGLImage(width, height, eglGetCurrentDisplay(),
eglGetCurrentContext())) {
return false;
}

// Populate the texture object used by the engine.
opengl_texture->target = GL_TEXTURE_2D;
opengl_texture->name = state_->gl_texture;
#ifdef USE_GLES3
opengl_texture->format = GL_RGBA8;
#else
opengl_texture->format = GL_RGBA8_OES;
#endif
opengl_texture->destruction_callback = nullptr;
opengl_texture->user_data = nullptr;
opengl_texture->width = width;
opengl_texture->height = height;

return true;
}

bool ExternalTextureEGLImage::GetEGLImage(size_t& width,
size_t& height,
void* egl_display,
void* egl_context) {
using namespace std;

const FlutterDesktopEGLImage* egl_image =
texture_callback_(width, height, egl_display, egl_context, user_data_);
if (!egl_image || !egl_image->egl_image) {
return false;
}
width = egl_image->width;
height = egl_image->height;

if (state_->gl_texture == 0) {
gl_.glGenTextures(1, &state_->gl_texture);

gl_.glBindTexture(GL_TEXTURE_2D, state_->gl_texture);
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
gl_.glBindTexture(GL_TEXTURE_2D, state_->gl_texture);
}
gl_.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
(EGLImageKHR)egl_image->egl_image);

if (egl_image->release_callback) {
egl_image->release_callback(egl_image->release_context);
}
return true;
}

} // namespace flutter
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_EXTERNAL_TEXTURE_EGL_IMAGE_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_EXTERNAL_TEXTURE_EGL_IMAGE_H_

#include <stdint.h>

#include <memory>

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

#include "flutter/shell/platform/linux_embedded/external_texture.h"

namespace flutter {

typedef struct ExternalTextureEGLImageState ExternalTextureEGLImageState;

// An abstraction of an EGL Image based texture.
class ExternalTextureEGLImage : public ExternalTexture {
public:
ExternalTextureEGLImage(
FlutterDesktopEGLImageTextureCallback texture_callback,
void* user_data,
const GlProcs& gl_procs);

virtual ~ExternalTextureEGLImage();

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

private:
// Attempts to get the EGLImage returned by |texture_callback_| to
// OpenGL.
// The |width| and |height| will be set to the actual bounds of the EGLImage
// Returns true on success or false if the EGLImage returned
// by |texture_callback_| was invalid.
bool GetEGLImage(size_t& width,
size_t& height,
void* egl_display,
void* egl_context);

std::unique_ptr<ExternalTextureEGLImageState> state_;
FlutterDesktopEGLImageTextureCallback texture_callback_ = nullptr;
void* const user_data_ = nullptr;
const GlProcs& gl_;
};

} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_EXTERNAL_TEXTURE_EGL_IMAGE_H_
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <mutex>

#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
#include "flutter/shell/platform/linux_embedded/external_texture_egl_image.h"
#include "flutter/shell/platform/linux_embedded/external_texture_pixelbuffer.h"
#include "flutter/shell/platform/linux_embedded/flutter_elinux_engine.h"
#include "flutter/shell/platform/linux_embedded/flutter_elinux_view.h"
Expand Down Expand Up @@ -38,6 +39,15 @@ int64_t FlutterELinuxTextureRegistrar::RegisterTexture(
return EmplaceTexture(std::make_unique<flutter::ExternalTexturePixelBuffer>(
texture_info->pixel_buffer_config.callback,
texture_info->pixel_buffer_config.user_data, gl_procs_));
} else if (texture_info->type == kFlutterDesktopEGLImageTexture) {
if (!texture_info->egl_image_config.callback) {
std::cerr << "Invalid EGLImage texture callback." << std::endl;
return kInvalidTexture;
}

return EmplaceTexture(std::make_unique<flutter::ExternalTextureEGLImage>(
texture_info->egl_image_config.callback,
texture_info->egl_image_config.user_data, gl_procs_));
} else if (texture_info->type == kFlutterDesktopGpuSurfaceTexture) {
std::cerr << "GpuSurfaceTexture is not yet supported." << std::endl;
return kInvalidTexture;
Expand Down Expand Up @@ -114,10 +124,12 @@ void FlutterELinuxTextureRegistrar::ResolveGlFunctions(GlProcs& procs) {
eglGetProcAddress("glTexParameteri"));
procs.glTexImage2D =
reinterpret_cast<glTexImage2DProc>(eglGetProcAddress("glTexImage2D"));

procs.glEGLImageTargetTexture2DOES =
reinterpret_cast<glEGLImageTargetTexture2DOESProc>(
eglGetProcAddress("glEGLImageTargetTexture2DOES"));
procs.valid = procs.glGenTextures && procs.glDeleteTextures &&
procs.glBindTexture && procs.glTexParameteri &&
procs.glTexImage2D;
procs.glTexImage2D && procs.glEGLImageTargetTexture2DOES;
}

}; // namespace flutter