summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/context_rpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/context_rpi.c')
-rw-r--r--video/out/opengl/context_rpi.c327
1 files changed, 0 insertions, 327 deletions
diff --git a/video/out/opengl/context_rpi.c b/video/out/opengl/context_rpi.c
deleted file mode 100644
index 0b6babb..0000000
--- a/video/out/opengl/context_rpi.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-#include <stdatomic.h>
-#include <stddef.h>
-
-#include <bcm_host.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include "common/common.h"
-#include "video/out/win_state.h"
-#include "context.h"
-#include "egl_helpers.h"
-
-struct priv {
- struct GL gl;
- DISPMANX_DISPLAY_HANDLE_T display;
- DISPMANX_ELEMENT_HANDLE_T window;
- DISPMANX_UPDATE_HANDLE_T update;
- 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_int reload_display;
- int win_params[4];
-};
-
-static void tv_callback(void *callback_data, uint32_t reason, uint32_t param1,
- uint32_t param2)
-{
- struct ra_ctx *ctx = callback_data;
- struct priv *p = ctx->priv;
- atomic_store(&p->reload_display, true);
- vo_wakeup(ctx->vo);
-}
-
-static void destroy_dispmanx(struct ra_ctx *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);
- p->egl_surface = EGL_NO_SURFACE;
- }
-
- if (p->window)
- vc_dispmanx_element_remove(p->update, p->window);
- p->window = 0;
- if (p->display)
- vc_dispmanx_display_close(p->display);
- p->display = 0;
- if (p->update)
- vc_dispmanx_update_submit_sync(p->update);
- p->update = 0;
-}
-
-static void rpi_uninit(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
- ra_gl_ctx_uninit(ctx);
-
- vc_tv_unregister_callback_full(tv_callback, ctx);
-
- 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 bool recreate_dispmanx(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
- int display_nr = 0;
- int layer = 0;
-
- MP_VERBOSE(ctx, "Recreating DISPMANX state...\n");
-
- destroy_dispmanx(ctx);
-
- p->display = vc_dispmanx_display_open(display_nr);
- p->update = vc_dispmanx_update_start(0);
- if (!p->display || !p->update) {
- MP_FATAL(ctx, "Could not get DISPMANX objects.\n");
- goto fail;
- }
-
- uint32_t dispw, disph;
- if (graphics_get_display_size(0, &dispw, &disph) < 0) {
- MP_FATAL(ctx, "Could not get display size.\n");
- goto fail;
- }
- p->w = dispw;
- p->h = disph;
-
- if (ctx->vo->opts->fullscreen) {
- p->x = p->y = 0;
- } else {
- struct vo_win_geometry geo;
- struct mp_rect screenrc = {0, 0, p->w, p->h};
-
- vo_calc_window_geometry(ctx->vo, &screenrc, &geo);
-
- mp_rect_intersection(&geo.win, &screenrc);
-
- p->x = geo.win.x0;
- p->y = geo.win.y0;
- p->w = geo.win.x1 - geo.win.x0;
- p->h = geo.win.y1 - geo.win.y0;
- }
-
- // dispmanx is like a neanderthal version of Wayland - you can add an
- // overlay any place on the screen.
- VC_RECT_T dst = {.x = p->x, .y = p->y, .width = p->w, .height = p->h};
- VC_RECT_T src = {.width = p->w << 16, .height = p->h << 16};
- VC_DISPMANX_ALPHA_T alpha = {
- .flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,
- .opacity = 0xFF,
- };
- p->window = vc_dispmanx_element_add(p->update, p->display, layer, &dst, 0,
- &src, DISPMANX_PROTECTION_NONE, &alpha,
- 0, 0);
- if (!p->window) {
- MP_FATAL(ctx, "Could not add DISPMANX element.\n");
- goto fail;
- }
-
- vc_dispmanx_update_submit_sync(p->update);
- p->update = vc_dispmanx_update_start(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(ctx, "Could not create EGL surface!\n");
- goto fail;
- }
-
- if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
- p->egl_context))
- {
- MP_FATAL(ctx, "Failed to set context!\n");
- goto fail;
- }
-
- p->display_fps = 0;
- TV_GET_STATE_RESP_T tvstate;
- TV_DISPLAY_STATE_T tvstate_disp;
- if (!vc_tv_get_state(&tvstate) && !vc_tv_get_display_state(&tvstate_disp)) {
- if (tvstate_disp.state & (VC_HDMI_HDMI | VC_HDMI_DVI)) {
- p->display_fps = tvstate_disp.display.hdmi.frame_rate;
-
- HDMI_PROPERTY_PARAM_T param = {
- .property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE,
- };
- if (!vc_tv_hdmi_get_property(&param) &&
- param.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC)
- p->display_fps = p->display_fps / 1.001;
- } else {
- p->display_fps = tvstate_disp.display.sdtv.frame_rate;
- }
- }
-
- p->win_params[0] = display_nr;
- p->win_params[1] = layer;
- p->win_params[2] = p->x;
- p->win_params[3] = p->y;
-
- ctx->vo->dwidth = p->w;
- ctx->vo->dheight = p->h;
- if (ctx->swapchain)
- ra_gl_ctx_resize(ctx->swapchain, p->w, p->h, 0);
-
- ctx->vo->want_redraw = true;
-
- vo_event(ctx->vo, VO_EVENT_WIN_STATE);
- return true;
-
-fail:
- destroy_dispmanx(ctx);
- return false;
-}
-
-static void rpi_swap_buffers(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
- eglSwapBuffers(p->egl_display, p->egl_surface);
-}
-
-static bool rpi_init(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
-
- bcm_host_init();
-
- vc_tv_register_callback(tv_callback, ctx);
-
- p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (!eglInitialize(p->egl_display, NULL, NULL)) {
- MP_FATAL(ctx, "EGL failed to initialize.\n");
- goto fail;
- }
-
- if (!mpegl_create_context(ctx, p->egl_display, &p->egl_context, &p->egl_config))
- goto fail;
-
- if (!recreate_dispmanx(ctx))
- goto fail;
-
- mpegl_load_functions(&p->gl, ctx->log);
-
- struct ra_gl_ctx_params params = {
- .swap_buffers = rpi_swap_buffers,
- };
-
- if (!ra_gl_ctx_init(ctx, &p->gl, params))
- goto fail;
-
- ra_add_native_resource(ctx->ra, "MPV_RPI_WINDOW", p->win_params);
-
- ra_gl_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight, 0);
- return true;
-
-fail:
- rpi_uninit(ctx);
- return false;
-}
-
-static bool rpi_reconfig(struct ra_ctx *ctx)
-{
- return recreate_dispmanx(ctx);
-}
-
-static struct mp_image *take_screenshot(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
-
- if (!p->display)
- return NULL;
-
- struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h);
- if (!img)
- return NULL;
-
- DISPMANX_RESOURCE_HANDLE_T resource =
- vc_dispmanx_resource_create(VC_IMAGE_ARGB8888,
- img->w | ((img->w * 4) << 16), img->h,
- &(int32_t){0});
- if (!resource)
- goto fail;
-
- if (vc_dispmanx_snapshot(p->display, resource, 0))
- goto fail;
-
- VC_RECT_T rc = {.width = img->w, .height = img->h};
- if (vc_dispmanx_resource_read_data(resource, &rc, img->planes[0], img->stride[0]))
- goto fail;
-
- vc_dispmanx_resource_delete(resource);
- return img;
-
-fail:
- vc_dispmanx_resource_delete(resource);
- talloc_free(img);
- return NULL;
-}
-
-static int rpi_control(struct ra_ctx *ctx, int *events, int request, void *arg)
-{
- struct priv *p = ctx->priv;
-
- switch (request) {
- case VOCTRL_SCREENSHOT_WIN:
- *(struct mp_image **)arg = take_screenshot(ctx);
- return VO_TRUE;
- case VOCTRL_CHECK_EVENTS:
- if (atomic_fetch_and(&p->reload_display, 0)) {
- MP_WARN(ctx, "Recovering from display mode switch...\n");
- recreate_dispmanx(ctx);
- }
- return VO_TRUE;
- case VOCTRL_GET_DISPLAY_FPS:
- *(double *)arg = p->display_fps;
- return VO_TRUE;
- }
-
- return VO_NOTIMPL;
-}
-
-const struct ra_ctx_fns ra_ctx_rpi = {
- .type = "opengl",
- .name = "rpi",
- .reconfig = rpi_reconfig,
- .control = rpi_control,
- .init = rpi_init,
- .uninit = rpi_uninit,
-};