summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/src/glcontext_egl.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/src/glcontext_egl.cpp')
-rw-r--r--3rdparty/bgfx/src/glcontext_egl.cpp226
1 files changed, 156 insertions, 70 deletions
diff --git a/3rdparty/bgfx/src/glcontext_egl.cpp b/3rdparty/bgfx/src/glcontext_egl.cpp
index fabddd5c663..dde4ead37cb 100644
--- a/3rdparty/bgfx/src/glcontext_egl.cpp
+++ b/3rdparty/bgfx/src/glcontext_egl.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2022 Branimir Karadzic. All rights reserved.
+ * Copyright 2011-2023 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
@@ -15,6 +15,18 @@
# include <bcm_host.h>
# endif // BX_PLATFORM_RPI
+#define _EGL_CHECK(_check, _call) \
+ BX_MACRO_BLOCK_BEGIN \
+ EGLBoolean success = _call; \
+ _check(success, #_call "; EGL error 0x%x", eglGetError() ); \
+ BX_MACRO_BLOCK_END
+
+#if BGFX_CONFIG_DEBUG
+# define EGL_CHECK(_call) _EGL_CHECK(BX_ASSERT, _call)
+#else
+# define EGL_CHECK(_call) _call
+#endif // BGFX_CONFIG_DEBUG
+
namespace bgfx { namespace gl
{
#ifndef EGL_CONTEXT_FLAG_NO_ERROR_BIT_KHR
@@ -25,36 +37,44 @@ namespace bgfx { namespace gl
typedef void (*EGLPROC)(void);
- typedef EGLBoolean (EGLAPIENTRY* PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
- typedef EGLContext (EGLAPIENTRY* PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
- typedef EGLSurface (EGLAPIENTRY* PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
- typedef EGLint (EGLAPIENTRY* PFNEGLGETERRORPROC)(void);
- typedef EGLDisplay (EGLAPIENTRY* PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id);
- typedef EGLPROC (EGLAPIENTRY* PFNEGLGETPROCADDRESSPROC)(const char *procname);
- typedef EGLBoolean (EGLAPIENTRY* PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint *major, EGLint *minor);
- typedef EGLBoolean (EGLAPIENTRY* PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+ typedef EGLBoolean (EGLAPIENTRY* PGNEGLBINDAPIPROC)(EGLenum api);
+ typedef EGLBoolean (EGLAPIENTRY* PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
+ typedef EGLContext (EGLAPIENTRY* PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list);
+ typedef EGLSurface (EGLAPIENTRY* PFNEGLCREATEPBUFFERSURFACEPROC)(EGLDisplay display, EGLConfig config, EGLint const* attrib_list);
+ typedef EGLSurface (EGLAPIENTRY* PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list);
typedef EGLBoolean (EGLAPIENTRY* PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx);
typedef EGLBoolean (EGLAPIENTRY* PFNEGLDESTROYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface);
- typedef const char* (EGLAPIENTRY* PGNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
+ typedef EGLContext (EGLAPIENTRY* PFNEGLGETCURRENTCONTEXTPROC)(void);
+ typedef EGLSurface (EGLAPIENTRY* PFNEGLGETCURRENTSURFACEPROC)(EGLint readdraw);
+ typedef EGLDisplay (EGLAPIENTRY* PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id);
+ typedef EGLint (EGLAPIENTRY* PFNEGLGETERRORPROC)(void);
+ typedef EGLPROC (EGLAPIENTRY* PFNEGLGETPROCADDRESSPROC)(const char* procname);
+ typedef EGLBoolean (EGLAPIENTRY* PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint* major, EGLint* minor);
+ typedef EGLBoolean (EGLAPIENTRY* PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
typedef EGLBoolean (EGLAPIENTRY* PFNEGLSWAPBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface);
typedef EGLBoolean (EGLAPIENTRY* PFNEGLSWAPINTERVALPROC)(EGLDisplay dpy, EGLint interval);
typedef EGLBoolean (EGLAPIENTRY* PFNEGLTERMINATEPROC)(EGLDisplay dpy);
+ typedef const char* (EGLAPIENTRY* PGNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
-#define EGL_IMPORT \
- EGL_IMPORT_FUNC(PFNEGLCHOOSECONFIGPROC, eglChooseConfig); \
- EGL_IMPORT_FUNC(PFNEGLCREATECONTEXTPROC, eglCreateContext); \
- EGL_IMPORT_FUNC(PFNEGLCREATEWINDOWSURFACEPROC, eglCreateWindowSurface); \
- EGL_IMPORT_FUNC(PFNEGLGETDISPLAYPROC, eglGetDisplay); \
- EGL_IMPORT_FUNC(PFNEGLGETERRORPROC, eglGetError); \
- EGL_IMPORT_FUNC(PFNEGLGETPROCADDRESSPROC, eglGetProcAddress); \
- EGL_IMPORT_FUNC(PFNEGLDESTROYCONTEXTPROC, eglDestroyContext); \
- EGL_IMPORT_FUNC(PFNEGLDESTROYSURFACEPROC, eglDestroySurface); \
- EGL_IMPORT_FUNC(PFNEGLINITIALIZEPROC, eglInitialize); \
- EGL_IMPORT_FUNC(PFNEGLMAKECURRENTPROC, eglMakeCurrent); \
- EGL_IMPORT_FUNC(PGNEGLQUERYSTRINGPROC, eglQueryString); \
- EGL_IMPORT_FUNC(PFNEGLSWAPBUFFERSPROC, eglSwapBuffers); \
- EGL_IMPORT_FUNC(PFNEGLSWAPINTERVALPROC, eglSwapInterval); \
- EGL_IMPORT_FUNC(PFNEGLTERMINATEPROC, eglTerminate);
+#define EGL_IMPORT \
+ EGL_IMPORT_FUNC(PGNEGLBINDAPIPROC, eglBindAPI); \
+ EGL_IMPORT_FUNC(PFNEGLCHOOSECONFIGPROC, eglChooseConfig); \
+ EGL_IMPORT_FUNC(PFNEGLCREATECONTEXTPROC, eglCreateContext); \
+ EGL_IMPORT_FUNC(PFNEGLCREATEPBUFFERSURFACEPROC, eglCreatePbufferSurface); \
+ EGL_IMPORT_FUNC(PFNEGLCREATEWINDOWSURFACEPROC, eglCreateWindowSurface); \
+ EGL_IMPORT_FUNC(PFNEGLDESTROYCONTEXTPROC, eglDestroyContext); \
+ EGL_IMPORT_FUNC(PFNEGLDESTROYSURFACEPROC, eglDestroySurface); \
+ EGL_IMPORT_FUNC(PFNEGLGETCURRENTCONTEXTPROC, eglGetCurrentContext); \
+ EGL_IMPORT_FUNC(PFNEGLGETCURRENTSURFACEPROC, eglGetCurrentSurface); \
+ EGL_IMPORT_FUNC(PFNEGLGETDISPLAYPROC, eglGetDisplay); \
+ EGL_IMPORT_FUNC(PFNEGLGETERRORPROC, eglGetError); \
+ EGL_IMPORT_FUNC(PFNEGLGETPROCADDRESSPROC, eglGetProcAddress); \
+ EGL_IMPORT_FUNC(PFNEGLINITIALIZEPROC, eglInitialize); \
+ EGL_IMPORT_FUNC(PFNEGLMAKECURRENTPROC, eglMakeCurrent); \
+ EGL_IMPORT_FUNC(PFNEGLSWAPBUFFERSPROC, eglSwapBuffers); \
+ EGL_IMPORT_FUNC(PFNEGLSWAPINTERVALPROC, eglSwapInterval); \
+ EGL_IMPORT_FUNC(PFNEGLTERMINATEPROC, eglTerminate); \
+ EGL_IMPORT_FUNC(PGNEGLQUERYSTRINGPROC, eglQueryString); \
#define EGL_IMPORT_FUNC(_proto, _func) _proto _func
EGL_IMPORT
@@ -62,12 +82,19 @@ EGL_IMPORT
void* eglOpen()
{
- void* handle = bx::dlopen("libEGL." BX_DL_EXT);
+ void* handle = bx::dlopen(
+#if BX_PLATFORM_LINUX
+ "libEGL.so.1"
+#else
+ "libEGL." BX_DL_EXT
+#endif // BX_PLATFORM_*
+ );
+
BGFX_FATAL(NULL != handle, Fatal::UnableToInitialize, "Failed to load libEGL dynamic library.");
-#define EGL_IMPORT_FUNC(_proto, _func) \
- _func = (_proto)bx::dlsym(handle, #_func); \
- BX_TRACE("%p " #_func, _func); \
+#define EGL_IMPORT_FUNC(_proto, _func) \
+ _func = (_proto)bx::dlsym(handle, #_func); \
+ BX_TRACE("%p " #_func, _func); \
BGFX_FATAL(NULL != _func, Fatal::UnableToInitialize, "Failed get " #_func ".")
EGL_IMPORT
#undef EGL_IMPORT_FUNC
@@ -107,9 +134,17 @@ EGL_IMPORT
: m_nwh(_nwh)
, m_display(_display)
{
- EGLSurface defaultSurface = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface defaultSurface = eglGetCurrentSurface(EGL_DRAW);
+
+ if (EGLNativeWindowType(0) == _nwh)
+ {
+ m_surface = eglCreatePbufferSurface(m_display, _config, NULL);
+ }
+ else
+ {
+ m_surface = eglCreateWindowSurface(m_display, _config, _nwh, NULL);
+ }
- m_surface = eglCreateWindowSurface(m_display, _config, _nwh, NULL);
BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::UnableToInitialize, "Failed to create surface.");
m_context = eglCreateContext(m_display, _config, _context, s_contextAttrs);
@@ -119,30 +154,32 @@ EGL_IMPORT
GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) );
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
swapBuffers();
+
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) );
swapBuffers();
- eglMakeCurrent(m_display, defaultSurface, defaultSurface, _context);
+
+ EGL_CHECK(eglMakeCurrent(m_display, defaultSurface, defaultSurface, _context) );
}
~SwapChainGL()
{
- EGLSurface defaultSurface = eglGetCurrentSurface(EGL_DRAW);
- EGLContext defaultContext = eglGetCurrentContext();
+ EGLSurface defaultSurface = eglGetCurrentSurface(EGL_DRAW);
+ EGLContext defaultContext = eglGetCurrentContext();
- eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(m_display, m_context);
- eglDestroySurface(m_display, m_surface);
- eglMakeCurrent(m_display, defaultSurface, defaultSurface, defaultContext);
+ EGL_CHECK(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) );
+ EGL_CHECK(eglDestroyContext(m_display, m_context) );
+ EGL_CHECK(eglDestroySurface(m_display, m_surface) );
+ EGL_CHECK(eglMakeCurrent(m_display, defaultSurface, defaultSurface, defaultContext) );
}
void makeCurrent()
{
- eglMakeCurrent(m_display, m_surface, m_surface, m_context);
+ EGL_CHECK(eglMakeCurrent(m_display, m_surface, m_surface, m_context) );
}
void swapBuffers()
{
- eglSwapBuffers(m_display, m_surface);
+ EGL_CHECK(eglSwapBuffers(m_display, m_surface) );
}
EGLNativeWindowType m_nwh;
@@ -157,6 +194,8 @@ EGL_IMPORT
void GlContext::create(uint32_t _width, uint32_t _height, uint32_t _flags)
{
+ BX_UNUSED(_flags);
+
# if BX_PLATFORM_RPI
bcm_host_init();
# endif // BX_PLATFORM_RPI
@@ -180,7 +219,7 @@ EGL_IMPORT
}
# endif // BX_PLATFORM_WINDOWS
- m_display = eglGetDisplay(ndt);
+ m_display = eglGetDisplay(NULL == ndt ? EGL_DEFAULT_DISPLAY : ndt);
BGFX_FATAL(m_display != EGL_NO_DISPLAY, Fatal::UnableToInitialize, "Failed to create display %p", m_display);
EGLint major = 0;
@@ -202,24 +241,39 @@ EGL_IMPORT
BX_TRACE("Supported EGL extensions:");
dumpExtensions(extensions);
- // https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_recordable.txt
+ if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) )
+ {
+ EGLBoolean ok = eglBindAPI(EGL_OPENGL_API);
+ BGFX_FATAL(ok, Fatal::UnableToInitialize, "Could not set API! error: %d", eglGetError());
+ }
+
const bool hasEglAndroidRecordable = !bx::findIdentifierMatch(extensions, "EGL_ANDROID_recordable").isEmpty();
- const uint32_t gles = BGFX_CONFIG_RENDERER_OPENGLES;
+ const uint32_t glVersion = !!BGFX_CONFIG_RENDERER_OPENGL
+ ? BGFX_CONFIG_RENDERER_OPENGL
+ : BGFX_CONFIG_RENDERER_OPENGLES
+ ;
#if BX_PLATFORM_ANDROID
- uint32_t msaa = (_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT;
- uint32_t msaaSamples = msaa == 0 ? 0 : 1<<msaa;
+ const uint32_t msaa = (_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT;
+ const uint32_t msaaSamples = msaa == 0 ? 0 : 1<<msaa;
m_msaaContext = true;
#endif // BX_PLATFORM_ANDROID
+ const bool headless = EGLNativeWindowType(0) == nwh;
+
EGLint attrs[] =
{
- EGL_RENDERABLE_TYPE, (gles >= 30) ? EGL_OPENGL_ES3_BIT_KHR : EGL_OPENGL_ES2_BIT,
+ EGL_RENDERABLE_TYPE, !!BGFX_CONFIG_RENDERER_OPENGL
+ ? EGL_OPENGL_BIT
+ : (glVersion >= 30) ? EGL_OPENGL_ES3_BIT_KHR : EGL_OPENGL_ES2_BIT
+ ,
- EGL_BLUE_SIZE, 8,
+ EGL_SURFACE_TYPE, headless ? EGL_PBUFFER_BIT : EGL_WINDOW_BIT,
+
+ EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
- EGL_RED_SIZE, 8,
+ EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
# if BX_PLATFORM_ANDROID
@@ -231,8 +285,8 @@ EGL_IMPORT
EGL_STENCIL_SIZE, 8,
// Android Recordable surface
- hasEglAndroidRecordable ? 0x3142 : EGL_NONE,
- hasEglAndroidRecordable ? 1 : EGL_NONE,
+ hasEglAndroidRecordable ? EGL_RECORDABLE_ANDROID : EGL_NONE,
+ hasEglAndroidRecordable ? 1 : EGL_NONE,
EGL_NONE
};
@@ -274,7 +328,23 @@ EGL_IMPORT
vc_dispmanx_update_submit_sync(dispmanUpdate);
# endif // BX_PLATFORM_ANDROID
- m_surface = eglCreateWindowSurface(m_display, m_config, nwh, NULL);
+ if (headless)
+ {
+ EGLint pbAttribs[] =
+ {
+ EGL_WIDTH, EGLint(1),
+ EGL_HEIGHT, EGLint(1),
+
+ EGL_NONE
+ };
+
+ m_surface = eglCreatePbufferSurface(m_display, m_config, pbAttribs);
+ }
+ else
+ {
+ m_surface = eglCreateWindowSurface(m_display, m_config, nwh, NULL);
+ }
+
BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::UnableToInitialize, "Failed to create surface.");
const bool hasEglKhrCreateContext = !bx::findIdentifierMatch(extensions, "EGL_KHR_create_context").isEmpty();
@@ -291,11 +361,17 @@ EGL_IMPORT
# else
if (hasEglKhrCreateContext)
{
- bx::write(&writer, EGLint(EGL_CONTEXT_MAJOR_VERSION_KHR), bx::ErrorAssert{} );
- bx::write(&writer, EGLint(gles / 10), bx::ErrorAssert{} );
+ if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) )
+ {
+ bx::write(&writer, EGLint(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR), bx::ErrorAssert{});
+ bx::write(&writer, EGLint(EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR), bx::ErrorAssert{});
+ }
+
+ bx::write(&writer, EGLint(EGL_CONTEXT_MAJOR_VERSION_KHR), bx::ErrorAssert{});
+ bx::write(&writer, EGLint(glVersion / 10), bx::ErrorAssert{});
- bx::write(&writer, EGLint(EGL_CONTEXT_MINOR_VERSION_KHR), bx::ErrorAssert{} );
- bx::write(&writer, EGLint(gles % 10), bx::ErrorAssert{} );
+ bx::write(&writer, EGLint(EGL_CONTEXT_MINOR_VERSION_KHR), bx::ErrorAssert{});
+ bx::write(&writer, EGLint(glVersion % 10), bx::ErrorAssert{});
flags |= BGFX_CONFIG_DEBUG && hasEglKhrNoError ? 0
| EGL_CONTEXT_FLAG_NO_ERROR_BIT_KHR
@@ -318,7 +394,7 @@ EGL_IMPORT
# endif // BX_PLATFORM_RPI
{
bx::write(&writer, EGLint(EGL_CONTEXT_CLIENT_VERSION), bx::ErrorAssert{} );
- bx::write(&writer, EGLint(gles / 10), bx::ErrorAssert{} );
+ bx::write(&writer, EGLint(glVersion / 10), bx::ErrorAssert{} );
}
bx::write(&writer, EGLint(EGL_NONE), bx::ErrorAssert{} );
@@ -350,10 +426,10 @@ EGL_IMPORT
{
if (NULL != m_display)
{
- eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(m_display, m_context);
- eglDestroySurface(m_display, m_surface);
- eglTerminate(m_display);
+ EGL_CHECK(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) );
+ EGL_CHECK(eglDestroyContext(m_display, m_context) );
+ EGL_CHECK(eglDestroySurface(m_display, m_surface) );
+ EGL_CHECK(eglTerminate(m_display) );
m_context = NULL;
}
@@ -390,17 +466,17 @@ EGL_IMPORT
if (NULL != m_display)
{
bool vsync = !!(_flags&BGFX_RESET_VSYNC);
- eglSwapInterval(m_display, vsync ? 1 : 0);
+ EGL_CHECK(eglSwapInterval(m_display, vsync ? 1 : 0) );
}
}
uint64_t GlContext::getCaps() const
{
return BX_ENABLED(0
- | BX_PLATFORM_LINUX
- | BX_PLATFORM_WINDOWS
- | BX_PLATFORM_ANDROID
- )
+ | BX_PLATFORM_LINUX
+ | BX_PLATFORM_WINDOWS
+ | BX_PLATFORM_ANDROID
+ )
? BGFX_CAPS_SWAP_CHAIN
: 0
;
@@ -413,7 +489,7 @@ EGL_IMPORT
void GlContext::destroySwapChain(SwapChainGL* _swapChain)
{
- BX_DELETE(g_allocator, _swapChain);
+ bx::deleteObject(g_allocator, _swapChain);
}
void GlContext::swap(SwapChainGL* _swapChain)
@@ -424,7 +500,7 @@ EGL_IMPORT
{
if (NULL != m_display)
{
- eglSwapBuffers(m_display, m_surface);
+ EGL_CHECK(eglSwapBuffers(m_display, m_surface) );
}
}
else
@@ -443,7 +519,7 @@ EGL_IMPORT
{
if (NULL != m_display)
{
- eglMakeCurrent(m_display, m_surface, m_surface, m_context);
+ EGL_CHECK(eglMakeCurrent(m_display, m_surface, m_surface, m_context) );
}
}
else
@@ -458,13 +534,23 @@ EGL_IMPORT
BX_TRACE("Import:");
# if BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX
- void* glesv2 = bx::dlopen("libGLESv2." BX_DL_EXT);
+# if BX_PLATFORM_WINDOWS
+# define LIBRARY_NAME "libGL.dll"
+# elif BX_PLATFORM_LINUX
+# if BGFX_CONFIG_RENDERER_OPENGL
+# define LIBRARY_NAME "libGL.so.1"
+# else
+# define LIBRARY_NAME "libGLESv2.so.2"
+# endif
+# endif
+
+ void* lib = bx::dlopen(LIBRARY_NAME);
# define GL_EXTENSION(_optional, _proto, _func, _import) \
{ \
if (NULL == _func) \
{ \
- _func = bx::dlsym<_proto>(glesv2, #_import); \
+ _func = bx::dlsym<_proto>(lib, #_import); \
BX_TRACE("\t%p " #_func " (" #_import ")", _func); \
BGFX_FATAL(_optional || NULL != _func \
, Fatal::UnableToInitialize \