Issue #3079 - Use desktop OpenGL for X11 EGL

This commit is contained in:
Basilisk-Dev
2026-05-04 19:17:24 -04:00
committed by roytam1
parent f8ad674b35
commit 5f72c9b23b
2 changed files with 122 additions and 87 deletions
+99 -67
View File
@@ -13,13 +13,23 @@
#if defined(XP_UNIX)
#define GLES2_LIB "libGLESv2.so"
#define GLES2_LIB2 "libGLESv2.so.2"
#if defined(MOZ_X11)
#if defined(__OpenBSD__) || defined(__NetBSD__)
#define EGL_OPENGL_LIB "libGL.so"
#define EGL_OPENGL_LIB2 "libGL.so.1"
#else
#define EGL_OPENGL_LIB "libGL.so.1"
#define EGL_OPENGL_LIB2 "libGL.so"
#endif
#else
#define EGL_OPENGL_LIB "libGLESv2.so"
#define EGL_OPENGL_LIB2 "libGLESv2.so.2"
#endif
#elif defined(XP_WIN)
#include "nsIFile.h"
#define GLES2_LIB "libGLESv2.dll"
#define EGL_OPENGL_LIB "libGLESv2.dll"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
@@ -102,6 +112,45 @@ using namespace mozilla::widget;
static bool
CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget);
static bool
UseDesktopOpenGLForEGL()
{
#ifdef MOZ_X11
return true;
#else
return false;
#endif
}
static EGLint
GetEGLRenderableType(CreateContextFlags flags)
{
if (UseDesktopOpenGLForEGL()) {
return LOCAL_EGL_OPENGL_BIT;
}
return bool(flags & CreateContextFlags::PREFER_ES3)
? LOCAL_EGL_OPENGL_ES3_BIT_KHR
: LOCAL_EGL_OPENGL_ES2_BIT;
}
static bool
BindContextAPI(nsACString* const out_failureId)
{
const EGLenum api = UseDesktopOpenGLForEGL()
? LOCAL_EGL_OPENGL_API
: LOCAL_EGL_OPENGL_ES_API;
if (sEGLLibrary.fBindAPI(api) == LOCAL_EGL_FALSE) {
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_BIND_API");
NS_WARNING(UseDesktopOpenGLForEGL()
? "Failed to bind API to OpenGL!"
: "Failed to bind API to GLES!");
return false;
}
return true;
}
// append three zeros at the end of attribs list to work around
// EGL implementation bugs that iterate until they find 0, instead of
// EGL_NONE. See bug 948406.
@@ -172,8 +221,12 @@ GLContextEGL::GLContextEGL(CreateContextFlags flags, const SurfaceCaps& caps,
, mShareWithEGLImage(false)
, mOwnsContext(true)
{
// any EGL contexts will always be GLESv2
SetProfileVersion(ContextProfile::OpenGLES, 200);
// X11 uses desktop OpenGL-over-EGL. Other EGL paths still use GLES/ANGLE.
if (UseDesktopOpenGLForEGL()) {
SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
} else {
SetProfileVersion(ContextProfile::OpenGLES, 200);
}
#ifdef DEBUG
printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
@@ -202,10 +255,10 @@ GLContextEGL::~GLContextEGL()
bool
GLContextEGL::Init()
{
if (!OpenLibrary(GLES2_LIB)) {
if (!OpenLibrary(EGL_OPENGL_LIB)) {
#if defined(XP_UNIX)
if (!OpenLibrary(GLES2_LIB2)) {
NS_WARNING("Couldn't load GLES2 LIB.");
if (!OpenLibrary(EGL_OPENGL_LIB2)) {
NS_WARNING("Couldn't load EGL GL library.");
return false;
}
#endif
@@ -451,9 +504,7 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
EGLSurface surface,
nsACString* const out_failureId)
{
if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_ES");
NS_WARNING("Failed to bind API to GLES!");
if (!BindContextAPI(out_failureId)) {
return nullptr;
}
@@ -462,11 +513,14 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
nsTArray<EGLint> contextAttribs;
contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_CLIENT_VERSION);
if (flags & CreateContextFlags::PREFER_ES3)
contextAttribs.AppendElement(3);
else
contextAttribs.AppendElement(2);
if (!UseDesktopOpenGLForEGL()) {
contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_CLIENT_VERSION);
if (flags & CreateContextFlags::PREFER_ES3) {
contextAttribs.AppendElement(3);
} else {
contextAttribs.AppendElement(2);
}
}
if (sEGLLibrary.HasRobustness()) {
// contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT);
@@ -550,70 +604,52 @@ TRY_AGAIN_POWER_OF_TWO:
return surface;
}
static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT,
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
// Old versions of llvmpipe seem to need this to properly create the pbuffer (bug 981856)
LOCAL_EGL_RED_SIZE, 8,
LOCAL_EGL_GREEN_SIZE, 8,
LOCAL_EGL_BLUE_SIZE, 8,
LOCAL_EGL_ALPHA_SIZE, 0,
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
};
static void
AppendWindowConfigAttribs(int32_t depth, nsTArray<EGLint>* out)
{
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
out->AppendElement(LOCAL_EGL_WINDOW_BIT);
static const EGLint kEGLConfigAttribsRGB16[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
LOCAL_EGL_RED_SIZE, 5,
LOCAL_EGL_GREEN_SIZE, 6,
LOCAL_EGL_BLUE_SIZE, 5,
LOCAL_EGL_ALPHA_SIZE, 0,
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
};
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
out->AppendElement(GetEGLRenderableType(CreateContextFlags::NONE));
static const EGLint kEGLConfigAttribsRGB24[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
LOCAL_EGL_RED_SIZE, 8,
LOCAL_EGL_GREEN_SIZE, 8,
LOCAL_EGL_BLUE_SIZE, 8,
LOCAL_EGL_ALPHA_SIZE, 0,
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
};
out->AppendElement(LOCAL_EGL_RED_SIZE);
out->AppendElement(depth == 16 ? 5 : 8);
static const EGLint kEGLConfigAttribsRGBA32[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
LOCAL_EGL_RED_SIZE, 8,
LOCAL_EGL_GREEN_SIZE, 8,
LOCAL_EGL_BLUE_SIZE, 8,
LOCAL_EGL_ALPHA_SIZE, 8,
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
};
out->AppendElement(LOCAL_EGL_GREEN_SIZE);
out->AppendElement(depth == 16 ? 6 : 8);
out->AppendElement(LOCAL_EGL_BLUE_SIZE);
out->AppendElement(depth == 16 ? 5 : 8);
out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
out->AppendElement(depth == 32 ? 8 : 0);
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(gTerminationAttribs); ++i) {
out->AppendElement(gTerminationAttribs[i]);
}
}
static bool
CreateConfig(EGLConfig* aConfig, int32_t depth, nsIWidget* aWidget)
{
EGLConfig configs[64];
const EGLint* attribs;
EGLint ncfg = ArrayLength(configs);
nsTArray<EGLint> attribs;
switch (depth) {
case 16:
attribs = kEGLConfigAttribsRGB16;
break;
case 24:
attribs = kEGLConfigAttribsRGB24;
break;
case 32:
attribs = kEGLConfigAttribsRGBA32;
break;
default:
NS_ERROR("Unknown pixel depth");
return false;
}
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs,
AppendWindowConfigAttribs(depth, &attribs);
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs.Elements(),
configs, ncfg, &ncfg) ||
ncfg < 1) {
return false;
@@ -727,17 +763,13 @@ GLContextProviderEGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated
static void
FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
bool es3, nsTArray<EGLint>* out)
CreateContextFlags flags, nsTArray<EGLint>* out)
{
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
if (es3) {
out->AppendElement(LOCAL_EGL_OPENGL_ES3_BIT_KHR);
} else {
out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
}
out->AppendElement(GetEGLRenderableType(flags));
out->AppendElement(LOCAL_EGL_RED_SIZE);
if (bpp16) {
@@ -797,7 +829,7 @@ ChooseConfig(GLLibraryEGL* egl, CreateContextFlags flags, const SurfaceCaps& min
{
nsTArray<EGLint> configAttribList;
FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16,
bool(flags & CreateContextFlags::PREFER_ES3), &configAttribList);
flags, &configAttribList);
const EGLint* configAttribs = configAttribList.Elements();
+23 -20
View File
@@ -43,6 +43,14 @@
#include "mozilla/Unused.h"
#if defined(__OpenBSD__) || defined(__NetBSD__)
# define LIBGL_FILENAME "libGL.so"
# define LIBGL_FILENAME_FALLBACK "libGL.so.1"
#else
# define LIBGL_FILENAME "libGL.so.1"
# define LIBGL_FILENAME_FALLBACK "libGL.so"
#endif
// stuff from glx.h
typedef struct __GLXcontextRec *GLXContext;
typedef XID GLXPixmap;
@@ -189,7 +197,7 @@ try_egltest(std::string* aError)
{
static const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
@@ -202,7 +210,6 @@ try_egltest(std::string* aError)
EGL_NONE
};
static const EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
@@ -211,8 +218,8 @@ try_egltest(std::string* aError)
return false;
}
void* libgles = nullptr;
if (!load_library("libGLESv2.so", "libGLESv2.so.2", &libgles, aError)) {
void* libgl = nullptr;
if (!load_library(LIBGL_FILENAME, LIBGL_FILENAME_FALLBACK, &libgl, aError)) {
dlclose(libegl);
return false;
}
@@ -242,7 +249,7 @@ try_egltest(std::string* aError)
PFNEGLDESTROYSURFACE eglDestroySurface = cast<PFNEGLDESTROYSURFACE>(dlsym(libegl, "eglDestroySurface"));
PFNEGLTERMINATE eglTerminate = cast<PFNEGLTERMINATE>(dlsym(libegl, "eglTerminate"));
PFNEGLGETERROR eglGetError = cast<PFNEGLGETERROR>(dlsym(libegl, "eglGetError"));
PFNGLGETSTRING glGetString = cast<PFNGLGETSTRING>(dlsym(libgles, "glGetString"));
PFNGLGETSTRING glGetString = cast<PFNGLGETSTRING>(dlsym(libgl, "glGetString"));
if (!eglGetDisplay ||
!eglInitialize ||
@@ -257,8 +264,8 @@ try_egltest(std::string* aError)
!eglGetError ||
!glGetString)
{
*aError = "EGL probe couldn't find required EGL/GLES symbols";
dlclose(libgles);
*aError = "EGL probe couldn't find required EGL/OpenGL symbols";
dlclose(libgl);
dlclose(libegl);
return false;
}
@@ -266,7 +273,7 @@ try_egltest(std::string* aError)
Display* dpy = XOpenDisplay(nullptr);
if (!dpy) {
*aError = "Unable to open a connection to the X server";
dlclose(libgles);
dlclose(libgl);
dlclose(libegl);
return false;
}
@@ -296,8 +303,8 @@ try_egltest(std::string* aError)
goto egltest_error;
}
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
*aError = "EGL probe could not bind the OpenGL ES API";
if (!eglBindAPI(EGL_OPENGL_API)) {
*aError = "EGL probe could not bind the OpenGL API";
goto egltest_error;
}
@@ -364,7 +371,7 @@ try_egltest(std::string* aError)
XSync(dpy, False);
#endif
dlclose(libgles);
dlclose(libgl);
dlclose(libegl);
write_to_pipe(buf, length);
@@ -384,7 +391,7 @@ egltest_error:
#else
XSync(dpy, False);
#endif
dlclose(libgles);
dlclose(libgl);
dlclose(libegl);
return false;
}
@@ -454,14 +461,10 @@ void glxtest()
}
///// Open libGL and load needed symbols /////
#if defined(__OpenBSD__) || defined(__NetBSD__)
#define LIBGL_FILENAME "libGL.so"
#else
#define LIBGL_FILENAME "libGL.so.1"
#endif
void *libgl = dlopen(LIBGL_FILENAME, RTLD_LAZY);
if (!libgl)
fatal_error("Unable to load " LIBGL_FILENAME);
void* libgl = nullptr;
std::string libglError;
if (!load_library(LIBGL_FILENAME, LIBGL_FILENAME_FALLBACK, &libgl, &libglError))
fatal_error(libglError.c_str());
typedef void* (* PFNGLXGETPROCADDRESS) (const char *);
PFNGLXGETPROCADDRESS glXGetProcAddress = cast<PFNGLXGETPROCADDRESS>(dlsym(libgl, "glXGetProcAddress"));