diff options
Diffstat (limited to 'video/out/opengl/context_rpi.c')
-rw-r--r-- | video/out/opengl/context_rpi.c | 327 |
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(¶m) && - 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, -}; |