diff options
author | Scott Anderson <ascent12@hotmail.com> | 2017-05-03 17:04:41 +1200 |
---|---|---|
committer | Scott Anderson <ascent12@hotmail.com> | 2017-05-03 17:04:41 +1200 |
commit | dbceaee9faaaf24016024bd22b38fa0186bb5e08 (patch) | |
tree | 3389de75acdb565243166aea7ff4cf6dd31bed8b /backend | |
parent | 81998fdc98231cb1b2e050da2fcec7c75d46320c (diff) |
Added EGL interface for backends.
Diffstat (limited to 'backend')
-rw-r--r-- | backend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | backend/egl.c | 169 |
2 files changed, 170 insertions, 0 deletions
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index ee8b04d6..938dc1ab 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(wlr-backend drm/backend.c drm/drm.c drm/udev.c + egl.c ) target_link_libraries(wlr-backend diff --git a/backend/egl.c b/backend/egl.c new file mode 100644 index 00000000..b6c49846 --- /dev/null +++ b/backend/egl.c @@ -0,0 +1,169 @@ +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <gbm.h> // GBM_FORMAT_XRGB8888 + +#include "backend/egl.h" +#include "common/log.h" + +static const char *egl_error(void) { + switch (eglGetError()) { + case EGL_SUCCESS: + return "Success"; + case EGL_NOT_INITIALIZED: + return "Not initialized"; + case EGL_BAD_ACCESS: + return "Bad access"; + case EGL_BAD_ALLOC: + return "Bad alloc"; + case EGL_BAD_ATTRIBUTE: + return "Bad attribute"; + case EGL_BAD_CONTEXT: + return "Bad Context"; + case EGL_BAD_CONFIG: + return "Bad Config"; + case EGL_BAD_CURRENT_SURFACE: + return "Bad current surface"; + case EGL_BAD_DISPLAY: + return "Bad display"; + case EGL_BAD_SURFACE: + return "Bad surface"; + case EGL_BAD_MATCH: + return "Bad match"; + case EGL_BAD_PARAMETER: + return "Bad parameter"; + case EGL_BAD_NATIVE_PIXMAP: + return "Bad native pixmap"; + case EGL_BAD_NATIVE_WINDOW: + return "Bad native window"; + case EGL_CONTEXT_LOST: + return "Context lost"; + default: + return "Unknown"; + } +} + +// EGL extensions +PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display; +PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window_surface; + +static bool egl_exts() { + get_platform_display = (PFNEGLGETPLATFORMDISPLAYEXTPROC) + eglGetProcAddress("eglGetPlatformDisplayEXT"); + + if (!get_platform_display) { + wlr_log(L_ERROR, "Failed to load EGL extension 'eglGetPlatformDisplayEXT'"); + return false; + } + + create_platform_window_surface = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) + eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); + + if (!get_platform_display) { + wlr_log(L_ERROR, + "Failed to load EGL extension 'eglCreatePlatformWindowSurfaceEXT'"); + return false; + } + + return true; +} + +static bool egl_get_config(EGLDisplay disp, EGLConfig *out) { + EGLint count = 0, matched = 0, ret; + + ret = eglGetConfigs(disp, NULL, 0, &count); + if (ret == EGL_FALSE || count == 0) { + return false; + } + + EGLConfig configs[count]; + + ret = eglChooseConfig(disp, NULL, configs, count, &matched); + if (ret == EGL_FALSE) { + return false; + } + + for (int i = 0; i < matched; ++i) { + EGLint gbm_format; + + if (!eglGetConfigAttrib(disp, + configs[i], + EGL_NATIVE_VISUAL_ID, + &gbm_format)) { + continue; + } + + // XXX: Is GBM_FORMAT_XRGB8888 what we want? + // I don't know if this works for wl_displays. + if (gbm_format == GBM_FORMAT_XRGB8888) { + *out = configs[i]; + return true; + } + } + + return false; +} + + +bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *display) { + if (!egl_exts()) { + return false; + } + + if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { + wlr_log(L_ERROR, "Failed to bind to the OpenGL ES API: %s", egl_error()); + goto error; + } + + egl->display = get_platform_display(platform, display, NULL); + if (egl->display == EGL_NO_DISPLAY) { + wlr_log(L_ERROR, "Failed to create EGL display: %s", egl_error()); + goto error; + } + + if (eglInitialize(egl->display, NULL, NULL) == EGL_FALSE) { + wlr_log(L_ERROR, "Failed to initialize EGL: %s", egl_error()); + goto error; + } + + if (!egl_get_config(egl->display, &egl->config)) { + wlr_log(L_ERROR, "Failed to get EGL config"); + goto error; + } + + static const EGLint attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; + + egl->context = eglCreateContext(egl->display, egl->config, + EGL_NO_CONTEXT, attribs); + + if (egl->context == EGL_NO_CONTEXT) { + wlr_log(L_ERROR, "Failed to create EGL context: %s", egl_error()); + goto error; + } + + return true; + +error: + eglTerminate(egl->display); + eglReleaseThread(); + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + return false; +} + +void wlr_egl_free(struct wlr_egl *egl) { + eglDestroyContext(egl->display, egl->context); + eglTerminate(egl->display); + eglReleaseThread(); + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) { + EGLSurface surf = create_platform_window_surface(egl->display, egl->config, + window, NULL); + if (surf == EGL_NO_SURFACE) { + wlr_log(L_ERROR, "Failed to create EGL surface: %s", egl_error()); + return EGL_NO_SURFACE; + } + + return surf; +} |