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

EGL: Use EGL_EXT_platform_base whenever possible #92663

Merged
merged 1 commit into from
Jun 13, 2024
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
89 changes: 68 additions & 21 deletions drivers/egl/egl_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,22 @@
#ifdef EGL_ENABLED

#if defined(EGL_STATIC)
#define KHRONOS_STATIC 1

#define GLAD_EGL_VERSION_1_5 true

#ifdef EGL_EXT_platform_base
#define GLAD_EGL_EXT_platform_base 1
#endif

#define KHRONOS_STATIC 1
extern "C" EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
#undef KHRONOS_STATIC

#endif // defined(EGL_STATIC)

#ifndef EGL_EXT_platform_base
#define GLAD_EGL_EXT_platform_base 0
#endif

// Creates and caches a GLDisplay. Returns -1 on error.
Expand All @@ -56,10 +68,23 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
if (GLAD_EGL_VERSION_1_5) {
Vector<EGLAttrib> attribs = _get_platform_display_attributes();
new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
} else if (GLAD_EGL_EXT_platform_base) {
#ifdef EGL_EXT_platform_base
// eglGetPlatformDisplayEXT wants its attributes as EGLint, so we'll truncate
// what we already have. It's a bit naughty but I'm really not sure what else
// we could do here.
Vector<EGLint> attribs;
for (const EGLAttrib &attrib : _get_platform_display_attributes()) {
attribs.push_back((EGLint)attrib);
}

new_gldisplay.egl_display = eglGetPlatformDisplayEXT(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
#endif // EGL_EXT_platform_base
} else {
NativeDisplayType *native_display_type = (NativeDisplayType *)new_gldisplay.display;
new_gldisplay.egl_display = eglGetDisplay(*native_display_type);
}

ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, -1);

ERR_FAIL_COND_V_MSG(new_gldisplay.egl_display == EGL_NO_DISPLAY, -1, "Can't create an EGL display.");
Expand Down Expand Up @@ -326,30 +351,51 @@ EGLContext EGLManager::get_context(DisplayServer::WindowID p_window_id) {
return display.egl_context;
}

Error EGLManager::initialize() {
Error EGLManager::initialize(void *p_native_display) {
#if defined(GLAD_ENABLED) && !defined(EGL_STATIC)
// Passing a null display loads just the bare minimum to create one. We'll have
// to create a temporary test display and reload EGL with it to get a good idea
// of what version is supported on this machine. Currently we're looking for
// 1.5, the latest at the time of writing, which is actually pretty old.
if (!gladLoaderLoadEGL(nullptr)) {
// Loading EGL with a new display gets us just the bare minimum API. We'll then
// have to temporarily get a proper display and reload EGL once again to
// initialize everything else.
if (!gladLoaderLoadEGL(EGL_NO_DISPLAY)) {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
}

// NOTE: EGL_DEFAULT_DISPLAY returns whatever the O.S. deems suitable. I have
// no idea if this may cause problems with multiple display servers and if we
// should handle different EGL contexts in another way.
EGLDisplay tmp_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ERR_FAIL_COND_V(tmp_display == EGL_NO_DISPLAY, ERR_UNAVAILABLE);
EGLDisplay tmp_display = EGL_NO_DISPLAY;

if (GLAD_EGL_EXT_platform_base) {
#ifdef EGL_EXT_platform_base
// eglGetPlatformDisplayEXT wants its attributes as EGLint.
Vector<EGLint> attribs;
for (const EGLAttrib &attrib : _get_platform_display_attributes()) {
attribs.push_back((EGLint)attrib);
}
tmp_display = eglGetPlatformDisplayEXT(_get_platform_extension_enum(), p_native_display, attribs.ptr());
#endif // EGL_EXT_platform_base
} else {
WARN_PRINT("EGL: EGL_EXT_platform_base not found during init, using default platform.");
EGLNativeDisplayType *native_display_type = (EGLNativeDisplayType *)p_native_display;
tmp_display = eglGetDisplay(*native_display_type);
}

if (tmp_display == EGL_NO_DISPLAY) {
eglTerminate(tmp_display);
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't get a valid initial EGL display.");
}

eglInitialize(tmp_display, nullptr, nullptr);

int version = gladLoaderLoadEGL(tmp_display);
if (!version) {
eglTerminate(tmp_display);
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
}

int major = GLAD_VERSION_MAJOR(version);
int minor = GLAD_VERSION_MINOR(version);

ERR_FAIL_COND_V_MSG(!version, ERR_UNAVAILABLE, "Can't load EGL.");
print_verbose(vformat("Loaded EGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)));
print_verbose(vformat("Loaded EGL %d.%d", major, minor));

ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, "EGL version is too old!");
ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, vformat("EGL version is too old! %d.%d < 1.4", major, minor));

eglTerminate(tmp_display);
#endif
Expand Down Expand Up @@ -378,13 +424,14 @@ Error EGLManager::initialize() {
}
#endif

String extensions_string = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
// The above method should always work. If it doesn't, something's very wrong.
ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, ERR_BUG);
String client_extensions_string = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);

const char *platform = _get_platform_extension_name();
if (!extensions_string.split(" ").has(platform)) {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, vformat("EGL platform extension \"%s\" not found.", platform));
// If the above method fails, we don't support client extensions, so there's nothing to check.
if (eglGetError() == EGL_SUCCESS) {
const char *platform = _get_platform_extension_name();
if (!client_extensions_string.split(" ").has(platform)) {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, vformat("EGL platform extension \"%s\" not found.", platform));
}
}

return OK;
Expand Down
2 changes: 1 addition & 1 deletion drivers/egl/egl_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class EGLManager {

EGLContext get_context(DisplayServer::WindowID p_window_id);

Error initialize();
Error initialize(void *p_native_display = nullptr);

EGLManager();
virtual ~EGLManager();
Expand Down
28 changes: 15 additions & 13 deletions platform/linuxbsd/wayland/detect_prime_egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,6 @@

#include <stdlib.h>

#ifdef GLAD_ENABLED
#include "thirdparty/glad/glad/egl.h"
#include "thirdparty/glad/glad/gl.h"
#else
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GL/glcorearb.h>
#endif // GLAD_ENABLED

#include <cstring>

#include <sys/types.h>
Expand All @@ -57,15 +48,26 @@
#undef glGetString

// Runs inside a child. Exiting will not quit the engine.
void DetectPrimeEGL::create_context() {
void DetectPrimeEGL::create_context(EGLenum p_platform_enum) {
#if defined(GLAD_ENABLED)
if (!gladLoaderLoadEGL(nullptr)) {
print_verbose("Unable to load EGL, GPU detection skipped.");
quick_exit(1);
}
#endif

EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLDisplay egl_display = EGL_NO_DISPLAY;

if (GLAD_EGL_VERSION_1_5) {
egl_display = eglGetPlatformDisplay(p_platform_enum, nullptr, nullptr);
} else if (GLAD_EGL_EXT_platform_base) {
#ifdef EGL_EXT_platform_base
egl_display = eglGetPlatformDisplayEXT(p_platform_enum, nullptr, nullptr);
#endif
} else {
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
}

EGLConfig egl_config;
EGLContext egl_context = EGL_NO_CONTEXT;

Expand Down Expand Up @@ -110,7 +112,7 @@ void DetectPrimeEGL::create_context() {
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context);
}

int DetectPrimeEGL::detect_prime() {
int DetectPrimeEGL::detect_prime(EGLenum p_platform_enum) {
pid_t p;
int priorities[4] = {};
String vendors[4];
Expand Down Expand Up @@ -168,7 +170,7 @@ int DetectPrimeEGL::detect_prime() {

setenv("DRI_PRIME", itos(i).utf8().ptr(), 1);

create_context();
create_context(p_platform_enum);

PFNGLGETSTRINGPROC glGetString = (PFNGLGETSTRINGPROC)eglGetProcAddress("glGetString");
const char *vendor = (const char *)glGetString(GL_VENDOR);
Expand Down
28 changes: 26 additions & 2 deletions platform/linuxbsd/wayland/detect_prime_egl.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@
#ifdef GLES3_ENABLED
#ifdef EGL_ENABLED

#ifdef GLAD_ENABLED
#include "thirdparty/glad/glad/egl.h"
#include "thirdparty/glad/glad/gl.h"
#else
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GL/glcorearb.h>

#define GLAD_EGL_VERSION_1_5 1

#ifdef EGL_EXT_platform_base
#define GLAD_EGL_EXT_platform_base 1
#endif

#define KHRONOS_STATIC 1
extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
#undef KHRONOS_STATIC

#endif // GLAD_ENABLED

#ifndef EGL_EXT_platform_base
#define GLAD_EGL_EXT_platform_base 0
#endif

class DetectPrimeEGL {
private:
struct Vendor {
Expand All @@ -53,10 +77,10 @@ class DetectPrimeEGL {
{ nullptr, 0 }
};

static void create_context();
static void create_context(EGLenum p_platform_enum);

public:
static int detect_prime();
static int detect_prime(EGLenum p_platform_enum);
};

#endif // GLES3_ENABLED
Expand Down
6 changes: 3 additions & 3 deletions platform/linuxbsd/wayland/display_server_wayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1343,7 +1343,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win

if (prime_idx == -1) {
print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic.");
prime_idx = DetectPrimeEGL::detect_prime();
prime_idx = DetectPrimeEGL::detect_prime(EGL_PLATFORM_WAYLAND_KHR);
}

if (prime_idx) {
Expand All @@ -1356,7 +1356,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
if (rendering_driver == "opengl3") {
egl_manager = memnew(EGLManagerWayland);

if (egl_manager->initialize() != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) {
if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) {
memdelete(egl_manager);
egl_manager = nullptr;

Expand All @@ -1376,7 +1376,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
if (rendering_driver == "opengl3_es") {
egl_manager = memnew(EGLManagerWaylandGLES);

if (egl_manager->initialize() != OK) {
if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK) {
memdelete(egl_manager);
egl_manager = nullptr;
r_error = ERR_CANT_CREATE;
Expand Down
6 changes: 6 additions & 0 deletions thirdparty/glad/EGL/eglplatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;

#elif defined(__QNX__)

typedef khronos_uintptr_t EGLNativeDisplayType;
typedef struct _screen_pixmap* EGLNativePixmapType; /* screen_pixmap_t */
typedef struct _screen_window* EGLNativeWindowType; /* screen_window_t */

#elif defined(__EMSCRIPTEN__)

typedef int EGLNativeDisplayType;
Expand Down
12 changes: 12 additions & 0 deletions thirdparty/glad/egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ int GLAD_EGL_VERSION_1_3 = 0;
int GLAD_EGL_VERSION_1_4 = 0;
int GLAD_EGL_VERSION_1_5 = 0;
int GLAD_EGL_ANDROID_blob_cache = 0;
int GLAD_EGL_EXT_platform_base = 0;
int GLAD_EGL_KHR_platform_wayland = 0;
int GLAD_EGL_KHR_platform_x11 = 0;

Expand All @@ -46,7 +47,9 @@ PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC glad_eglCreatePbufferFromClientBuffer =
PFNEGLCREATEPBUFFERSURFACEPROC glad_eglCreatePbufferSurface = NULL;
PFNEGLCREATEPIXMAPSURFACEPROC glad_eglCreatePixmapSurface = NULL;
PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC glad_eglCreatePlatformPixmapSurface = NULL;
PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC glad_eglCreatePlatformPixmapSurfaceEXT = NULL;
PFNEGLCREATEPLATFORMWINDOWSURFACEPROC glad_eglCreatePlatformWindowSurface = NULL;
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC glad_eglCreatePlatformWindowSurfaceEXT = NULL;
PFNEGLCREATESYNCPROC glad_eglCreateSync = NULL;
PFNEGLCREATEWINDOWSURFACEPROC glad_eglCreateWindowSurface = NULL;
PFNEGLDESTROYCONTEXTPROC glad_eglDestroyContext = NULL;
Expand All @@ -61,6 +64,7 @@ PFNEGLGETCURRENTSURFACEPROC glad_eglGetCurrentSurface = NULL;
PFNEGLGETDISPLAYPROC glad_eglGetDisplay = NULL;
PFNEGLGETERRORPROC glad_eglGetError = NULL;
PFNEGLGETPLATFORMDISPLAYPROC glad_eglGetPlatformDisplay = NULL;
PFNEGLGETPLATFORMDISPLAYEXTPROC glad_eglGetPlatformDisplayEXT = NULL;
PFNEGLGETPROCADDRESSPROC glad_eglGetProcAddress = NULL;
PFNEGLGETSYNCATTRIBPROC glad_eglGetSyncAttrib = NULL;
PFNEGLINITIALIZEPROC glad_eglInitialize = NULL;
Expand Down Expand Up @@ -145,6 +149,12 @@ static void glad_egl_load_EGL_ANDROID_blob_cache( GLADuserptrloadfunc load, void
if(!GLAD_EGL_ANDROID_blob_cache) return;
glad_eglSetBlobCacheFuncsANDROID = (PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) load(userptr, "eglSetBlobCacheFuncsANDROID");
}
static void glad_egl_load_EGL_EXT_platform_base( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_EGL_EXT_platform_base) return;
glad_eglCreatePlatformPixmapSurfaceEXT = (PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) load(userptr, "eglCreatePlatformPixmapSurfaceEXT");
glad_eglCreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) load(userptr, "eglCreatePlatformWindowSurfaceEXT");
glad_eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC) load(userptr, "eglGetPlatformDisplayEXT");
}



Expand Down Expand Up @@ -183,6 +193,7 @@ static int glad_egl_find_extensions_egl(EGLDisplay display) {
if (!glad_egl_get_extensions(display, &extensions)) return 0;

GLAD_EGL_ANDROID_blob_cache = glad_egl_has_extension(extensions, "EGL_ANDROID_blob_cache");
GLAD_EGL_EXT_platform_base = glad_egl_has_extension(extensions, "EGL_EXT_platform_base");
GLAD_EGL_KHR_platform_wayland = glad_egl_has_extension(extensions, "EGL_KHR_platform_wayland");
GLAD_EGL_KHR_platform_x11 = glad_egl_has_extension(extensions, "EGL_KHR_platform_x11");

Expand Down Expand Up @@ -248,6 +259,7 @@ int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void* userp

if (!glad_egl_find_extensions_egl(display)) return 0;
glad_egl_load_EGL_ANDROID_blob_cache(load, userptr);
glad_egl_load_EGL_EXT_platform_base(load, userptr);


return version;
Expand Down
Loading
Loading