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/opengl/context_rpi.c | 269 +++++++++++------------------------------ video/out/opengl/context_rpi.h | 21 ---- video/out/vo_rpi.c | 130 +++++++++++++++++++- 3 files changed, 200 insertions(+), 220 deletions(-) delete mode 100644 video/out/opengl/context_rpi.h diff --git a/video/out/opengl/context_rpi.c b/video/out/opengl/context_rpi.c index ee2bacb939..5c9b81da01 100644 --- a/video/out/opengl/context_rpi.c +++ b/video/out/opengl/context_rpi.c @@ -18,199 +18,28 @@ #include #include +#include + +#include +#include + #include "common/common.h" #include "osdep/atomic.h" #include "video/out/win_state.h" #include "context.h" #include "egl_helpers.h" -#include "context_rpi.h" - -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; -} - -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; -} - -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 void mp_egl_rpi_destroy_base(struct mp_egl_rpi *p) -{ - if (p->egl_context) - eglDestroyContext(p->egl_display, p->egl_context); - p->egl_context = EGL_NO_CONTEXT; - eglReleaseThread(); - p->egl_display = EGL_NO_DISPLAY; -} - -static int mp_egl_rpi_init_base(struct mp_egl_rpi *p) -{ - p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (!eglInitialize(p->egl_display, NULL, NULL)) { - MP_FATAL(p, "EGL failed to initialize.\n"); - goto fail; - } - - if (!mpegl_create_context(p->egl_display, p->log, 0, &p->egl_context, - &p->egl_config)) - goto fail; - - return 0; - -fail: - mp_egl_rpi_destroy_base(p); - return -1; -} - -static int mp_egl_rpi_init_window(struct mp_egl_rpi *p, - DISPMANX_ELEMENT_HANDLE_T window, - int w, int h) -{ - p->egl_window = (EGL_DISPMANX_WINDOW_T){ - .element = window, - .width = w, - .height = h, - }; - p->egl_surface = eglCreateWindowSurface(p->egl_display, p->egl_config, - &p->egl_window, NULL); - - if (p->egl_surface == EGL_NO_SURFACE) { - MP_FATAL(p, "Could not create EGL surface!\n"); - return -1; - } - - if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, - p->egl_context)) - { - MP_FATAL(p, "Failed to set context!\n"); - return -1; - } - - return 0; -} - -static void mp_egl_rpi_destroy_window(struct mp_egl_rpi *p) -{ - if (p->egl_surface) { - eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - eglDestroySurface(p->egl_display, p->egl_surface); - p->egl_surface = EGL_NO_SURFACE; - } -} - struct priv { + struct mp_log *log; DISPMANX_DISPLAY_HANDLE_T display; DISPMANX_ELEMENT_HANDLE_T window; DISPMANX_UPDATE_HANDLE_T update; - struct mp_egl_rpi egl; + 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; int x, y, w, h; double display_fps; atomic_bool reload_display; @@ -230,7 +59,13 @@ static void destroy_dispmanx(struct MPGLContext *ctx) { struct priv *p = ctx->priv; - mp_egl_rpi_destroy_window(&p->egl); + if (p->egl_surface) { + eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglDestroySurface(p->egl_display, p->egl_surface); + p->egl_surface = EGL_NO_SURFACE; + } + if (p->window) vc_dispmanx_element_remove(p->update, p->window); p->window = 0; @@ -248,9 +83,13 @@ static void rpi_uninit(MPGLContext *ctx) vc_tv_unregister_callback_full(tv_callback, ctx); - mp_egl_rpi_destroy_base(&p->egl); - destroy_dispmanx(ctx); + + if (p->egl_context) + eglDestroyContext(p->egl_display, p->egl_context); + p->egl_context = EGL_NO_CONTEXT; + eglReleaseThread(); + p->egl_display = EGL_NO_DISPLAY; } static int recreate_dispmanx(struct MPGLContext *ctx) @@ -310,8 +149,25 @@ static int recreate_dispmanx(struct MPGLContext *ctx) vc_dispmanx_update_submit_sync(p->update); p->update = vc_dispmanx_update_start(0); - if (mp_egl_rpi_init_window(&p->egl, p->window, p->w, p->h) < 0) + p->egl_window = (EGL_DISPMANX_WINDOW_T){ + .element = p->window, + .width = p->w, + .height = p->h, + }; + p->egl_surface = eglCreateWindowSurface(p->egl_display, p->egl_config, + &p->egl_window, NULL); + + if (p->egl_surface == EGL_NO_SURFACE) { + MP_FATAL(p, "Could not create EGL surface!\n"); goto fail; + } + + if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, + p->egl_context)) + { + MP_FATAL(p, "Failed to set context!\n"); + goto fail; + } p->display_fps = 0; TV_GET_STATE_RESP_T tvstate; @@ -347,34 +203,51 @@ fail: return -1; } +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) + p = dlsym(RTLD_DEFAULT, name); + return p; +} + static int rpi_init(struct MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; + p->log = ctx->vo->log; bcm_host_init(); vc_tv_register_callback(tv_callback, ctx); - p->egl.log = ctx->vo->log; - if (mp_egl_rpi_init_base(&p->egl) < 0) { - rpi_uninit(ctx); - return -1; + p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(p->egl_display, NULL, NULL)) { + MP_FATAL(p, "EGL failed to initialize.\n"); + goto fail; } - if (recreate_dispmanx(ctx) < 0) { - rpi_uninit(ctx); - return -1; - } + if (!mpegl_create_context(p->egl_display, p->log, 0, &p->egl_context, + &p->egl_config)) + goto fail; + + if (recreate_dispmanx(ctx) < 0) + goto fail; ctx->gl = talloc_zero(ctx, GL); - const char *exts = eglQueryString(p->egl.egl_display, EGL_EXTENSIONS); - mpgl_load_functions(ctx->gl, get_proc_address, exts, p->egl.log); + const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS); + mpgl_load_functions(ctx->gl, get_proc_address, exts, p->log); ctx->native_display_type = "MPV_RPI_WINDOW"; ctx->native_display = p->win_params; return 0; + +fail: + rpi_uninit(ctx); + return -1; } static int rpi_reconfig(struct MPGLContext *ctx) @@ -385,7 +258,7 @@ static int rpi_reconfig(struct MPGLContext *ctx) static void rpi_swap_buffers(MPGLContext *ctx) { struct priv *p = ctx->priv; - eglSwapBuffers(p->egl.egl_display, p->egl.egl_surface); + eglSwapBuffers(p->egl_display, p->egl_surface); } static struct mp_image *take_screenshot(struct MPGLContext *ctx) diff --git a/video/out/opengl/context_rpi.h b/video/out/opengl/context_rpi.h deleted file mode 100644 index 60bd9c72d2..0000000000 --- a/video/out/opengl/context_rpi.h +++ /dev/null @@ -1,21 +0,0 @@ -#include - -#include -#include - -#include "common.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; -}; - -int mp_egl_rpi_init(struct mp_egl_rpi *p, DISPMANX_ELEMENT_HANDLE_T window, - int w, int h); -void mp_egl_rpi_destroy(struct mp_egl_rpi *p); 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