summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/context_rpi.c
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2024-02-03 14:27:46 -0600
committerDudemanguy <random342@airmail.cc>2024-02-05 17:41:06 +0000
commit343a5fd345a84572ea5693a805119067d5b0fbc8 (patch)
tree4fbce1c7408194fe9f605d29d194525d30d92927 /video/out/opengl/context_rpi.c
parent8ecb462a9c2d8003e9972fd20dd2bb713389ed2c (diff)
downloadmpv-343a5fd345a84572ea5693a805119067d5b0fbc8.tar.bz2
mpv-343a5fd345a84572ea5693a805119067d5b0fbc8.tar.xz
player: remove all rpi-specific code
vo_rpi and its related code has pretty much historically been a disaster in mpv. The build regularly gets broken and since nobody uses it, it takes months for anyone to notice. There was also that time where fullscreen was broken for about a year and a half. Also building in waf was entirely broken for about a couple of years or so due to mysterious reasons no one ever figured out (meson magically fixed it). Anyways, once again the build is broken due to rpi being forgotten about again, but instead of pretending to support this crap. Just drop it all. Nowadays, mmal hwdec is a relic since these devices are better off using the v4l2m2m ffmpeg fork instead which actually uses KMS properly. RPI 1 and 2 probably can't do this and will remain broken but oh well blame Broadcom for being special snowflakes and not using standard APIs (my rockpro worked out of the box; just saying). RPI 2 is nearly 10 years old anyways, so I think you can afford a new SBC by now. If we were nicer, there would be a deprecation period, but this is broken in the last major release anyway so too late. Closes #13402.
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 0b6babbd1f..0000000000
--- 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,
-};