From 9def3682d159043cd5d6c32c22b15b3b9fc45c44 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 13 Sep 2016 20:30:03 +0200 Subject: vo_rpi, vo_opengl: separate RPI/EGL-specific code for both VOs This used to be shared, but since vo_rpi is going to be removed, untangle them. There was barely any actual code shared since the recent changes anyway. As a subtle change, we also stop opening libGLESv2.so explicitly in the vo_opengl backend, and use RTLD_DEFAULT instead. --- video/out/vo_rpi.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) (limited to 'video/out/vo_rpi.c') diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c index de5a8bf5e1..c046928f38 100644 --- a/video/out/vo_rpi.c +++ b/video/out/vo_rpi.c @@ -28,6 +28,9 @@ #include #include +#include +#include + #include #include "common/common.h" @@ -40,7 +43,17 @@ #include "sub/osd.h" #include "opengl/osd.h" -#include "opengl/context_rpi.h" + +struct mp_egl_rpi { + struct mp_log *log; + struct GL *gl; + EGLDisplay egl_display; + EGLConfig egl_config; + EGLContext egl_context; + EGLSurface egl_surface; + // yep, the API keeps a pointer to it + EGL_DISPMANX_WINDOW_T egl_window; +}; struct priv { DISPMANX_DISPLAY_HANDLE_T display; @@ -89,6 +102,121 @@ struct priv { static void recreate_renderer(struct vo *vo); +static void *get_proc_address(const GLubyte *name) +{ + void *p = eglGetProcAddress(name); + // EGL 1.4 (supported by the RPI firmware) does not necessarily return + // function pointers for core functions. + if (!p) { + void *h = dlopen("/opt/vc/lib/libGLESv2.so", RTLD_LAZY); + if (h) { + p = dlsym(h, name); + dlclose(h); + } + } + return p; +} + +static EGLConfig select_fb_config_egl(struct mp_egl_rpi *p) +{ + EGLint attributes[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_DEPTH_SIZE, 0, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + EGLint config_count; + EGLConfig config; + + eglChooseConfig(p->egl_display, attributes, &config, 1, &config_count); + + if (!config_count) { + MP_FATAL(p, "Could find EGL configuration!\n"); + return NULL; + } + + return config; +} + +static void mp_egl_rpi_destroy(struct mp_egl_rpi *p) +{ + if (p->egl_display) { + eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + } + if (p->egl_surface) + eglDestroySurface(p->egl_display, p->egl_surface); + if (p->egl_context) + eglDestroyContext(p->egl_display, p->egl_context); + p->egl_context = EGL_NO_CONTEXT; + eglReleaseThread(); + p->egl_display = EGL_NO_DISPLAY; + talloc_free(p->gl); + p->gl = NULL; +} + +static int mp_egl_rpi_init(struct mp_egl_rpi *p, DISPMANX_ELEMENT_HANDLE_T window, + int w, int h) +{ + p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(p->egl_display, NULL, NULL)) { + MP_FATAL(p, "EGL failed to initialize.\n"); + goto fail; + } + + eglBindAPI(EGL_OPENGL_ES_API); + + EGLConfig config = select_fb_config_egl(p); + if (!config) + goto fail; + + p->egl_window = (EGL_DISPMANX_WINDOW_T){ + .element = window, + .width = w, + .height = h, + }; + p->egl_surface = eglCreateWindowSurface(p->egl_display, config, + &p->egl_window, NULL); + + if (p->egl_surface == EGL_NO_SURFACE) { + MP_FATAL(p, "Could not create EGL surface!\n"); + goto fail; + } + + EGLint context_attributes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + p->egl_context = eglCreateContext(p->egl_display, config, + EGL_NO_CONTEXT, context_attributes); + + if (p->egl_context == EGL_NO_CONTEXT) { + MP_FATAL(p, "Could not create EGL context!\n"); + goto fail; + } + + eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, + p->egl_context); + + p->gl = talloc_zero(NULL, struct GL); + + const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS); + mpgl_load_functions(p->gl, get_proc_address, exts, p->log); + + if (!p->gl->version && !p->gl->es) + goto fail; + + return 0; + +fail: + mp_egl_rpi_destroy(p); + return -1; +} + // Make mpi point to buffer, assuming MMAL_ENCODING_I420. // buffer can be NULL. // Return the required buffer space. -- cgit v1.2.3