summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/context_drm_egl.c
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-09-14 08:04:55 +0200
committerNiklas Haas <git@haasn.xyz>2017-09-21 15:00:55 +0200
commit65979986a923a8f08019b257c3fe72cd5e8ecf68 (patch)
treeb8f4b8c17d583594aef0ca509064f8b2ff7128d4 /video/out/opengl/context_drm_egl.c
parent20f958c9775652c3213588c2a0824f5353276adc (diff)
downloadmpv-65979986a923a8f08019b257c3fe72cd5e8ecf68.tar.bz2
mpv-65979986a923a8f08019b257c3fe72cd5e8ecf68.tar.xz
vo_opengl: refactor into vo_gpu
This is done in several steps: 1. refactor MPGLContext -> struct ra_ctx 2. move GL-specific stuff in vo_opengl into opengl/context.c 3. generalize context creation to support other APIs, and add --gpu-api 4. rename all of the --opengl- options that are no longer opengl-specific 5. move all of the stuff from opengl/* that isn't GL-specific into gpu/ (note: opengl/gl_utils.h became opengl/utils.h) 6. rename vo_opengl to vo_gpu 7. to handle window screenshots, the short-term approach was to just add it to ra_swchain_fns. Long term (and for vulkan) this has to be moved to ra itself (and vo_gpu altered to compensate), but this was a stop-gap measure to prevent this commit from getting too big 8. move ra->fns->flush to ra_gl_ctx instead 9. some other minor changes that I've probably already forgotten Note: This is one half of a major refactor, the other half of which is provided by rossy's following commit. This commit enables support for all linux platforms, while his version enables support for all non-linux platforms. Note 2: vo_opengl_cb.c also re-uses ra_gl_ctx so it benefits from the --opengl- options like --opengl-early-flush, --opengl-finish etc. Should be a strict superset of the old functionality. Disclaimer: Since I have no way of compiling mpv on all platforms, some of these ports were done blindly. Specifically, the blind ports included context_mali_fbdev.c and context_rpi.c. Since they're both based on egl_helpers, the port should have gone smoothly without any major changes required. But if somebody complains about a compile error on those platforms (assuming anybody actually uses them), you know where to complain.
Diffstat (limited to 'video/out/opengl/context_drm_egl.c')
-rw-r--r--video/out/opengl/context_drm_egl.c194
1 files changed, 89 insertions, 105 deletions
diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c
index e52fec451b..21b16a52d5 100644
--- a/video/out/opengl/context_drm_egl.c
+++ b/video/out/opengl/context_drm_egl.c
@@ -28,10 +28,12 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "context.h"
-#include "egl_helpers.h"
-#include "common/common.h"
#include "video/out/drm_common.h"
+#include "common/common.h"
+
+#include "egl_helpers.h"
+#include "common.h"
+#include "context.h"
#define USE_MASTER 0
@@ -59,6 +61,7 @@ struct egl
};
struct priv {
+ GL gl;
struct kms *kms;
drmEventContext ev;
@@ -75,34 +78,33 @@ struct priv {
struct vt_switcher vt_switcher;
};
-static bool init_egl(struct MPGLContext *ctx, int flags)
+static bool init_egl(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
- MP_VERBOSE(ctx->vo, "Initializing EGL\n");
+ MP_VERBOSE(ctx, "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");
+ MP_ERR(ctx, "Failed to get EGL display.\n");
return false;
}
if (!eglInitialize(p->egl.display, NULL, NULL)) {
- MP_ERR(ctx->vo, "Failed to initialize EGL.\n");
+ MP_ERR(ctx, "Failed to initialize EGL.\n");
return false;
}
EGLConfig config;
- if (!mpegl_create_context(p->egl.display, ctx->vo->log, flags,
- &p->egl.context, &config))
- return -1;
- MP_VERBOSE(ctx->vo, "Initializing EGL surface\n");
+ if (!mpegl_create_context(ctx, p->egl.display, &p->egl.context, &config))
+ return false;
+ MP_VERBOSE(ctx, "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");
+ MP_ERR(ctx, "Failed to create EGL surface.\n");
return false;
}
return true;
}
-static bool init_gbm(struct MPGLContext *ctx)
+static bool init_gbm(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
MP_VERBOSE(ctx->vo, "Creating GBM device\n");
@@ -136,7 +138,7 @@ static void framebuffer_destroy_callback(struct gbm_bo *bo, void *data)
}
static void update_framebuffer_from_bo(
- const struct MPGLContext *ctx, struct gbm_bo *bo)
+ const struct ra_ctx *ctx, struct gbm_bo *bo)
{
struct priv *p = ctx->priv;
p->fb.bo = bo;
@@ -161,7 +163,7 @@ static void page_flipped(int fd, unsigned int frame, unsigned int sec,
p->waiting_for_flip = false;
}
-static bool crtc_setup(struct MPGLContext *ctx)
+static bool crtc_setup(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
if (p->active)
@@ -174,7 +176,7 @@ static bool crtc_setup(struct MPGLContext *ctx)
return ret == 0;
}
-static void crtc_release(struct MPGLContext *ctx)
+static void crtc_release(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -204,7 +206,7 @@ static void crtc_release(struct MPGLContext *ctx)
static void release_vt(void *data)
{
- struct MPGLContext *ctx = data;
+ struct ra_ctx *ctx = data;
MP_VERBOSE(ctx->vo, "Releasing VT");
crtc_release(ctx);
if (USE_MASTER) {
@@ -221,7 +223,7 @@ static void release_vt(void *data)
static void acquire_vt(void *data)
{
- struct MPGLContext *ctx = data;
+ struct ra_ctx *ctx = data;
MP_VERBOSE(ctx->vo, "Acquiring VT");
if (USE_MASTER) {
struct priv *p = ctx->priv;
@@ -234,11 +236,41 @@ static void acquire_vt(void *data)
crtc_setup(ctx);
}
-static void drm_egl_uninit(MPGLContext *ctx)
+static void drm_egl_swap_buffers(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
- crtc_release(ctx);
+ 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;
+}
+static void drm_egl_uninit(struct ra_ctx *ctx)
+{
+ struct priv *p = ctx->priv;
+ ra_gl_ctx_uninit(ctx);
+
+ crtc_release(ctx);
if (p->vt_switcher_active)
vt_switcher_destroy(&p->vt_switcher);
@@ -258,19 +290,14 @@ static void drm_egl_uninit(MPGLContext *ctx)
}
}
-static int drm_egl_init(struct MPGLContext *ctx, int flags)
+static bool drm_egl_init(struct ra_ctx *ctx)
{
- if (ctx->vo->probing) {
- MP_VERBOSE(ctx->vo, "DRM EGL backend can be activated only manually.\n");
- return -1;
+ if (ctx->opts.probing) {
+ MP_VERBOSE(ctx, "DRM EGL backend can be activated only manually.\n");
+ return false;
}
- 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;
+
+ struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
p->ev.version = DRM_EVENT_CONTEXT_VERSION;
p->ev.page_flip_handler = page_flipped;
@@ -279,79 +306,76 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
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_WARN(ctx, "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, ctx->vo->opts->drm_connector_spec,
+ MP_VERBOSE(ctx, "Initializing KMS\n");
+ p->kms = kms_create(ctx->log, ctx->vo->opts->drm_connector_spec,
ctx->vo->opts->drm_mode_id);
if (!p->kms) {
MP_ERR(ctx->vo, "Failed to create KMS.\n");
- return -1;
+ return false;
}
if (!init_gbm(ctx)) {
MP_ERR(ctx->vo, "Failed to setup GBM.\n");
- return -1;
+ return false;
}
- if (!init_egl(ctx, flags)) {
+ if (!init_egl(ctx)) {
MP_ERR(ctx->vo, "Failed to setup EGL.\n");
- return -1;
+ return false;
}
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;
+ return false;
}
- mpegl_load_functions(ctx->gl, ctx->vo->log);
-
- ctx->native_display_type = "drm";
- ctx->native_display = (void *)(intptr_t)p->kms->fd;
-
+ mpegl_load_functions(&p->gl, ctx->vo->log);
// required by gbm_surface_lock_front_buffer
eglSwapBuffers(p->egl.display, p->egl.surface);
- MP_VERBOSE(ctx->vo, "Preparing framebuffer\n");
+ MP_VERBOSE(ctx, "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;
+ MP_ERR(ctx, "Failed to lock GBM surface.\n");
+ return false;
}
update_framebuffer_from_bo(ctx, p->gbm.bo);
if (!p->fb.id) {
- MP_ERR(ctx->vo, "Failed to create framebuffer.\n");
- return -1;
+ MP_ERR(ctx, "Failed to create framebuffer.\n");
+ return false;
}
if (!crtc_setup(ctx)) {
- MP_ERR(ctx->vo, "Failed to set CRTC for connector %u: %s\n",
+ MP_ERR(ctx, "Failed to set CRTC for connector %u: %s\n",
p->kms->connector->connector_id, mp_strerror(errno));
- return -1;
+ return false;
}
- return 0;
-}
+ struct ra_gl_ctx_params params = {
+ .swap_buffers = drm_egl_swap_buffers,
+ .native_display_type = "drm",
+ .native_display = (void *)(intptr_t)p->kms->fd,
+ };
+ if (!ra_gl_ctx_init(ctx, &p->gl, params))
+ return false;
-static int drm_egl_init_deprecated(struct MPGLContext *ctx, int flags)
-{
- if (ctx->vo->probing)
- return -1;
- MP_WARN(ctx->vo, "'drm-egl' is deprecated, use 'drm' instead.\n");
- return drm_egl_init(ctx, flags);
+ return true;
}
-static int drm_egl_reconfig(struct MPGLContext *ctx)
+static bool drm_egl_reconfig(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
ctx->vo->dwidth = p->fb.width;
ctx->vo->dheight = p->fb.height;
- return 0;
+ ra_gl_ctx_resize(ctx->swapchain, p->fb.width, p->fb.height, 0);
+ return true;
}
-static int drm_egl_control(struct MPGLContext *ctx, int *events, int request,
+static int drm_egl_control(struct ra_ctx *ctx, int *events, int request,
void *arg)
{
struct priv *p = ctx->priv;
@@ -367,51 +391,11 @@ static int drm_egl_control(struct MPGLContext *ctx, int *events, int request,
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 = {
+const struct ra_ctx_fns ra_ctx_drm_egl = {
+ .type = "opengl",
.name = "drm",
- .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,
-};
-
-const struct mpgl_driver mpgl_driver_drm_egl = {
- .name = "drm-egl",
- .priv_size = sizeof(struct priv),
- .init = drm_egl_init_deprecated,
- .reconfig = drm_egl_reconfig,
- .swap_buffers = drm_egl_swap_buffers,
.control = drm_egl_control,
+ .init = drm_egl_init,
.uninit = drm_egl_uninit,
};