summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/drm_egl.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-12-19 13:05:10 +0100
committerwm4 <wm4@nowhere>2015-12-19 14:14:12 +0100
commit4cc1861378c3b1e989b5d92ea49e3d02f5e4a65a (patch)
tree3ae36f802e733d4deae518efc04a0a38e068c3b8 /video/out/opengl/drm_egl.c
parent6154c1d06d38bd236a0adb57556f7d871b75469b (diff)
downloadmpv-4cc1861378c3b1e989b5d92ea49e3d02f5e4a65a.tar.bz2
mpv-4cc1861378c3b1e989b5d92ea49e3d02f5e4a65a.tar.xz
vo_opengl: prefix per-backend source files with context_
Diffstat (limited to 'video/out/opengl/drm_egl.c')
-rw-r--r--video/out/opengl/drm_egl.c439
1 files changed, 0 insertions, 439 deletions
diff --git a/video/out/opengl/drm_egl.c b/video/out/opengl/drm_egl.c
deleted file mode 100644
index 34029a1a34..0000000000
--- a/video/out/opengl/drm_egl.c
+++ /dev/null
@@ -1,439 +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 General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with mpv. If not, see <http://www.gnu.org/licenses/>.
- *
- * You can alternatively redistribute this file 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.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/poll.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <gbm.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GL/gl.h>
-
-#include "context.h"
-#include "common/common.h"
-#include "video/out/drm_common.h"
-
-#define USE_MASTER 0
-
-struct framebuffer
-{
- struct gbm_bo *bo;
- int width, height;
- int fd;
- int id;
-};
-
-struct gbm
-{
- struct gbm_surface *surface;
- struct gbm_device *device;
- struct gbm_bo *bo;
- struct gbm_bo *next_bo;
-};
-
-struct egl
-{
- EGLDisplay display;
- EGLContext context;
- EGLSurface surface;
-};
-
-struct priv {
- struct kms *kms;
-
- drmEventContext ev;
- drmModeCrtc *old_crtc;
-
- struct egl egl;
- struct gbm gbm;
- struct framebuffer fb;
-
- bool active;
- bool waiting_for_flip;
-
- bool vt_switcher_active;
- struct vt_switcher vt_switcher;
-};
-
-static EGLConfig select_fb_config_egl(struct MPGLContext *ctx, bool es)
-{
- struct priv *p = ctx->priv;
- const EGLint attributes[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 0,
- EGL_DEPTH_SIZE, 1,
- EGL_RENDERABLE_TYPE, es ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
- EGL_NONE
- };
- EGLint config_count;
- EGLConfig config;
- if (!eglChooseConfig(p->egl.display, attributes, &config, 1, &config_count)) {
- MP_FATAL(ctx->vo, "Failed to configure EGL.\n");
- return NULL;
- }
- if (!config_count) {
- MP_FATAL(ctx->vo, "Could not find EGL configuration!\n");
- return NULL;
- }
- return config;
-}
-
-static bool init_egl(struct MPGLContext *ctx, bool es)
-{
- struct priv *p = ctx->priv;
- MP_VERBOSE(ctx->vo, "Initializing EGL\n");
- p->egl.display = eglGetDisplay(p->gbm.device);
- if (p->egl.display == EGL_NO_DISPLAY) {
- MP_ERR(ctx->vo, "Failed to get EGL display.\n");
- return false;
- }
- if (!eglInitialize(p->egl.display, NULL, NULL)) {
- MP_ERR(ctx->vo, "Failed to initialize EGL.\n");
- return false;
- }
- if (!eglBindAPI(es ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) {
- MP_ERR(ctx->vo, "Failed to set EGL API version.\n");
- return false;
- }
- EGLConfig config = select_fb_config_egl(ctx, es);
- if (!config) {
- MP_ERR(ctx->vo, "Failed to configure EGL.\n");
- return false;
- }
- p->egl.context = eglCreateContext(p->egl.display, config, EGL_NO_CONTEXT, NULL);
- if (!p->egl.context) {
- MP_ERR(ctx->vo, "Failed to create EGL context.\n");
- return false;
- }
- MP_VERBOSE(ctx->vo, "Initializing EGL surface\n");
- p->egl.surface = eglCreateWindowSurface(p->egl.display, config, p->gbm.surface, NULL);
- if (p->egl.surface == EGL_NO_SURFACE) {
- MP_ERR(ctx->vo, "Failed to create EGL surface.\n");
- return false;
- }
- return true;
-}
-
-static bool init_gbm(struct MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- MP_VERBOSE(ctx->vo, "Creating GBM device\n");
- p->gbm.device = gbm_create_device(p->kms->fd);
- if (!p->gbm.device) {
- MP_ERR(ctx->vo, "Failed to create GBM device.\n");
- return false;
- }
-
- MP_VERBOSE(ctx->vo, "Initializing GBM surface (%d x %d)\n",
- p->kms->mode.hdisplay, p->kms->mode.vdisplay);
- p->gbm.surface = gbm_surface_create(
- p->gbm.device,
- p->kms->mode.hdisplay,
- p->kms->mode.vdisplay,
- GBM_BO_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
- if (!p->gbm.surface) {
- MP_ERR(ctx->vo, "Failed to create GBM surface.\n");
- return false;
- }
- return true;
-}
-
-static void framebuffer_destroy_callback(struct gbm_bo *bo, void *data)
-{
- struct framebuffer *fb = data;
- if (fb) {
- drmModeRmFB(fb->fd, fb->id);
- }
-}
-
-static void update_framebuffer_from_bo(
- const struct MPGLContext *ctx, struct gbm_bo *bo)
-{
- struct priv *p = ctx->priv;
- p->fb.bo = bo;
- p->fb.fd = p->kms->fd;
- p->fb.width = gbm_bo_get_width(bo);
- p->fb.height = gbm_bo_get_height(bo);
- int stride = gbm_bo_get_stride(bo);
- int handle = gbm_bo_get_handle(bo).u32;
-
- int ret = drmModeAddFB(p->kms->fd, p->fb.width, p->fb.height,
- 24, 32, stride, handle, &p->fb.id);
- if (ret) {
- MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno));
- }
- gbm_bo_set_user_data(bo, &p->fb, framebuffer_destroy_callback);
-}
-
-static void page_flipped(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *data)
-{
- struct priv *p = data;
- p->waiting_for_flip = false;
-}
-
-static bool crtc_setup(struct MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- if (p->active)
- return true;
- p->old_crtc = drmModeGetCrtc(p->kms->fd, p->kms->crtc_id);
- int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id,
- p->fb.id,
- 0,
- 0,
- &p->kms->connector->connector_id,
- 1,
- &p->kms->mode);
- p->active = true;
- return ret == 0;
-}
-
-static void crtc_release(struct MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
-
- if (!p->active)
- return;
- p->active = false;
-
- // wait for current page flip
- while (p->waiting_for_flip) {
- int ret = drmHandleEvent(p->kms->fd, &p->ev);
- if (ret) {
- MP_ERR(ctx->vo, "drmHandleEvent failed: %i\n", ret);
- break;
- }
- }
-
- if (p->old_crtc) {
- drmModeSetCrtc(p->kms->fd,
- p->old_crtc->crtc_id,
- p->old_crtc->buffer_id,
- p->old_crtc->x,
- p->old_crtc->y,
- &p->kms->connector->connector_id,
- 1,
- &p->old_crtc->mode);
- drmModeFreeCrtc(p->old_crtc);
- p->old_crtc = NULL;
- }
-}
-
-static void release_vt(void *data)
-{
- struct MPGLContext *ctx = data;
- MP_VERBOSE(ctx->vo, "Releasing VT");
- crtc_release(ctx);
- if (USE_MASTER) {
- //this function enables support for switching to x, weston etc.
- //however, for whatever reason, it can be called only by root users.
- //until things change, this is commented.
- struct priv *p = ctx->priv;
- if (drmDropMaster(p->kms->fd)) {
- MP_WARN(ctx->vo, "Failed to drop DRM master: %s\n", mp_strerror(errno));
- }
- }
-}
-
-static void acquire_vt(void *data)
-{
- struct MPGLContext *ctx = data;
- MP_VERBOSE(ctx->vo, "Acquiring VT");
- if (USE_MASTER) {
- struct priv *p = ctx->priv;
- if (drmSetMaster(p->kms->fd)) {
- MP_WARN(ctx->vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno));
- }
- }
-
- crtc_setup(ctx);
-}
-
-static void drm_egl_uninit(MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- crtc_release(ctx);
-
- if (p->vt_switcher_active)
- vt_switcher_destroy(&p->vt_switcher);
-
- eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(p->egl.display, p->egl.context);
- eglDestroySurface(p->egl.display, p->egl.surface);
- gbm_surface_destroy(p->gbm.surface);
- eglTerminate(p->egl.display);
- gbm_device_destroy(p->gbm.device);
- p->egl.context = EGL_NO_CONTEXT;
- eglDestroyContext(p->egl.display, p->egl.context);
-
- if (p->kms) {
- kms_destroy(p->kms);
- p->kms = 0;
- }
-}
-
-static int drm_egl_init(struct MPGLContext *ctx, int flags)
-{
- if (ctx->vo->probing) {
- MP_VERBOSE(ctx->vo, "DRM EGL backend can be activated only manually.\n");
- return -1;
- }
- struct priv *p = ctx->priv;
- p->kms = NULL;
- p->old_crtc = NULL;
- p->gbm.surface = NULL;
- p->gbm.device = NULL;
- p->active = false;
- p->waiting_for_flip = false;
- p->ev.version = DRM_EVENT_CONTEXT_VERSION;
- p->ev.page_flip_handler = page_flipped;
-
- p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, ctx->vo->log);
- if (p->vt_switcher_active) {
- vt_switcher_acquire(&p->vt_switcher, acquire_vt, ctx);
- vt_switcher_release(&p->vt_switcher, release_vt, ctx);
- } else {
- MP_WARN(ctx->vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
- }
-
- MP_VERBOSE(ctx->vo, "Initializing KMS\n");
- p->kms = kms_create(ctx->vo->log);
- if (!p->kms) {
- MP_ERR(ctx->vo, "Failed to create KMS.\n");
- return -1;
- }
-
- // TODO: arguments should be configurable
- if (!kms_setup(p->kms, "/dev/dri/card0", -1, 0)) {
- MP_ERR(ctx->vo, "Failed to configure KMS.\n");
- return -1;
- }
-
- if (!init_gbm(ctx)) {
- MP_ERR(ctx->vo, "Failed to setup GBM.\n");
- return -1;
- }
-
- if (!init_egl(ctx, flags & VOFLAG_GLES)) {
- MP_ERR(ctx->vo, "Failed to setup EGL.\n");
- return -1;
- }
-
- if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface, p->egl.context)) {
- MP_ERR(ctx->vo, "Failed to make context current.\n");
- return -1;
- }
-
- const char *egl_exts = eglQueryString(p->egl.display, EGL_EXTENSIONS);
- void *(*gpa)(const GLubyte*) = (void *(*)(const GLubyte*))eglGetProcAddress;
- mpgl_load_functions(ctx->gl, gpa, egl_exts, ctx->vo->log);
-
- // required by gbm_surface_lock_front_buffer
- eglSwapBuffers(p->egl.display, p->egl.surface);
-
- MP_VERBOSE(ctx->vo, "Preparing framebuffer\n");
- p->gbm.bo = gbm_surface_lock_front_buffer(p->gbm.surface);
- if (!p->gbm.bo) {
- MP_ERR(ctx->vo, "Failed to lock GBM surface.\n");
- return -1;
- }
- update_framebuffer_from_bo(ctx, p->gbm.bo);
- if (!p->fb.id) {
- MP_ERR(ctx->vo, "Failed to create framebuffer.\n");
- return -1;
- }
-
- if (!crtc_setup(ctx)) {
- MP_ERR(
- ctx->vo,
- "Failed to set CRTC for connector %u: %s\n",
- p->kms->connector->connector_id,
- mp_strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-static int drm_egl_reconfig(struct MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- ctx->vo->dwidth = p->fb.width;
- ctx->vo->dheight = p->fb.height;
- return 0;
-}
-
-static int drm_egl_control(struct MPGLContext *ctx, int *events, int request,
- void *arg)
-{
- return VO_NOTIMPL;
-}
-
-static void drm_egl_swap_buffers(MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- eglSwapBuffers(p->egl.display, p->egl.surface);
- p->gbm.next_bo = gbm_surface_lock_front_buffer(p->gbm.surface);
- p->waiting_for_flip = true;
- update_framebuffer_from_bo(ctx, p->gbm.next_bo);
- int ret = drmModePageFlip(p->kms->fd, p->kms->crtc_id, p->fb.id,
- DRM_MODE_PAGE_FLIP_EVENT, p);
- if (ret) {
- MP_WARN(ctx->vo, "Failed to queue page flip: %s\n", mp_strerror(errno));
- }
-
- // poll page flip finish event
- const int timeout_ms = 3000;
- struct pollfd fds[1] = { { .events = POLLIN, .fd = p->kms->fd } };
- poll(fds, 1, timeout_ms);
- if (fds[0].revents & POLLIN) {
- ret = drmHandleEvent(p->kms->fd, &p->ev);
- if (ret != 0) {
- MP_ERR(ctx->vo, "drmHandleEvent failed: %i\n", ret);
- return;
- }
- }
-
- gbm_surface_release_buffer(p->gbm.surface, p->gbm.bo);
- p->gbm.bo = p->gbm.next_bo;
-}
-
-const struct mpgl_driver mpgl_driver_drm_egl = {
- .name = "drm-egl",
- .priv_size = sizeof(struct priv),
- .init = drm_egl_init,
- .reconfig = drm_egl_reconfig,
- .swap_buffers = drm_egl_swap_buffers,
- .control = drm_egl_control,
- .uninit = drm_egl_uninit,
-};