From 0ccceecdc61ba913d7dc591432ebd3b00836b9bd Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 13 Sep 2016 17:03:24 +0200 Subject: vo_opengl: mali fbdev support Minimal support just for testing. Only the window surface creation (including size determination) is really platform specific, so this could be some generic thing with platform-specific support as some sort of sub-driver, but on the other hand I don't see much of a need for such a thing. While most of the fbdev usage is done by the EGL driver, using this fbdev ioctl is apparently the only way to get the display resolution. --- video/out/opengl/context.c | 4 + video/out/opengl/context_mali_fbdev.c | 167 ++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 video/out/opengl/context_mali_fbdev.c (limited to 'video/out') diff --git a/video/out/opengl/context.c b/video/out/opengl/context.c index a8058fb18c..a22227562a 100644 --- a/video/out/opengl/context.c +++ b/video/out/opengl/context.c @@ -45,6 +45,7 @@ extern const struct mpgl_driver mpgl_driver_angle; extern const struct mpgl_driver mpgl_driver_angle_es2; extern const struct mpgl_driver mpgl_driver_dxinterop; extern const struct mpgl_driver mpgl_driver_rpi; +extern const struct mpgl_driver mpgl_driver_mali; static const struct mpgl_driver *const backends[] = { #if HAVE_RPI @@ -78,6 +79,9 @@ static const struct mpgl_driver *const backends[] = { #if HAVE_EGL_DRM &mpgl_driver_drm_egl, #endif +#if HAVE_MALI_FBDEV + &mpgl_driver_mali, +#endif }; // 0-terminated list of desktop GL versions a backend should try to diff --git a/video/out/opengl/context_mali_fbdev.c b/video/out/opengl/context_mali_fbdev.c new file mode 100644 index 0000000000..e76d220939 --- /dev/null +++ b/video/out/opengl/context_mali_fbdev.c @@ -0,0 +1,167 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/common.h" +#include "context.h" +#include "egl_helpers.h" + +static bool get_fbdev_size(int *w, int *h) +{ + int fd = open("/dev/fb0", O_RDWR | O_CLOEXEC); + if (fd < 0) + return false; + + struct fb_var_screeninfo info = {0}; + bool ok = !ioctl(fd, FBIOGET_VSCREENINFO, &info); + if (ok) { + *w = info.xres; + *h = info.yres; + } + + close(fd); + + return ok; +} + +static void *get_proc_address(const GLubyte *name) +{ + void *p = eglGetProcAddress(name); + // EGL 1.4 (supported by the MALI drivers) does not necessarily return + // function pointers for core functions. + if (!p) + p = dlsym(RTLD_DEFAULT, name); + return p; +} + +struct priv { + struct mp_log *log; + struct GL *gl; + EGLDisplay egl_display; + EGLConfig egl_config; + EGLContext egl_context; + EGLSurface egl_surface; + struct fbdev_window egl_window; + int w, h; +}; + +static void mali_uninit(struct MPGLContext *ctx) +{ + struct priv *p = ctx->priv; + + if (p->egl_surface) { + eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglDestroySurface(p->egl_display, p->egl_surface); + } + if (p->egl_context) + eglDestroyContext(p->egl_display, p->egl_context); + eglReleaseThread(); +} + +static int mali_init(struct MPGLContext *ctx, int flags) +{ + struct priv *p = ctx->priv; + p->log = ctx->vo->log; + + if (!get_fbdev_size(&p->w, &p->h)) { + MP_FATAL(p, "Could not get fbdev size.\n"); + goto fail; + } + + p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(p->egl_display, NULL, NULL)) { + MP_FATAL(p, "EGL failed to initialize.\n"); + goto fail; + } + + EGLConfig config; + if (!mpegl_create_context(p->egl_display, p->log, flags, &p->egl_context, + &config)) + goto fail; + + p->egl_window = (struct fbdev_window){ + .width = p->w, + .height = p->h, + }; + + p->egl_surface = eglCreateWindowSurface(p->egl_display, config, + (EGLNativeWindowType)&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; + } + + ctx->gl = talloc_zero(ctx, GL); + + const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS); + mpgl_load_functions(ctx->gl, get_proc_address, exts, p->log); + + return 0; + +fail: + mali_uninit(ctx); + return -1; +} + +static int mali_reconfig(struct MPGLContext *ctx) +{ + struct priv *p = ctx->priv; + ctx->vo->dwidth = p->w; + ctx->vo->dheight = p->h; + return 0; +} + +static void mali_swap_buffers(MPGLContext *ctx) +{ + struct priv *p = ctx->priv; + eglSwapBuffers(p->egl_display, p->egl_surface); +} + +static int mali_control(MPGLContext *ctx, int *events, int request, void *arg) +{ + return VO_NOTIMPL; +} + +const struct mpgl_driver mpgl_driver_mali = { + .name = "mali-fbdev", + .priv_size = sizeof(struct priv), + .init = mali_init, + .reconfig = mali_reconfig, + .swap_buffers = mali_swap_buffers, + .control = mali_control, + .uninit = mali_uninit, +}; -- cgit v1.2.3