summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/context_drm_egl.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/opengl/context_drm_egl.c')
-rw-r--r--video/out/opengl/context_drm_egl.c483
1 files changed, 120 insertions, 363 deletions
diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c
index 022a2d2a45..da28093562 100644
--- a/video/out/opengl/context_drm_egl.c
+++ b/video/out/opengl/context_drm_egl.c
@@ -29,9 +29,11 @@
#include <drm_fourcc.h>
#include "libmpv/render_gl.h"
-#include "video/out/drm_common.h"
#include "common/common.h"
#include "osdep/timer.h"
+#include "video/out/drm_atomic.h"
+#include "video/out/drm_common.h"
+#include "video/out/present_sync.h"
#include "egl_helpers.h"
#include "common.h"
@@ -45,28 +47,18 @@
#define EGL_PLATFORM_GBM_KHR 0x31D7
#endif
-struct framebuffer
-{
- int fd;
- uint32_t width, height;
- uint32_t id;
-};
-
struct gbm_frame {
struct gbm_bo *bo;
- struct drm_vsync_tuple vsync;
};
-struct gbm
-{
+struct gbm {
struct gbm_surface *surface;
struct gbm_device *device;
struct gbm_frame **bo_queue;
unsigned int num_bos;
};
-struct egl
-{
+struct egl {
EGLDisplay display;
EGLContext context;
EGLSurface surface;
@@ -74,13 +66,9 @@ struct egl
struct priv {
GL gl;
- struct kms *kms;
-
- drmEventContext ev;
struct egl egl;
struct gbm gbm;
- struct framebuffer *fb;
GLsync *vsync_fences;
unsigned int num_vsync_fences;
@@ -89,18 +77,6 @@ struct priv {
uint64_t *gbm_modifiers;
unsigned int num_gbm_modifiers;
- bool active;
- bool waiting_for_flip;
-
- bool vt_switcher_active;
- struct vt_switcher vt_switcher;
-
- bool still;
- bool paused;
-
- struct drm_vsync_tuple vsync;
- struct vo_vsync_info vsync_info;
-
struct mpv_opengl_drm_params_v2 drm_params;
struct mpv_opengl_drm_draw_surface_size draw_surface_size;
};
@@ -245,8 +221,9 @@ static bool init_egl(struct ra_ctx *ctx)
static bool init_gbm(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+ struct vo_drm_state *drm = ctx->vo->drm;
MP_VERBOSE(ctx->vo, "Creating GBM device\n");
- p->gbm.device = gbm_create_device(p->kms->fd);
+ p->gbm.device = gbm_create_device(drm->fd);
if (!p->gbm.device) {
MP_ERR(ctx->vo, "Failed to create GBM device.\n");
return false;
@@ -288,14 +265,15 @@ static void framebuffer_destroy_callback(struct gbm_bo *bo, void *data)
static void update_framebuffer_from_bo(struct ra_ctx *ctx, struct gbm_bo *bo)
{
struct priv *p = ctx->priv;
+ struct vo_drm_state *drm = ctx->vo->drm;
struct framebuffer *fb = gbm_bo_get_user_data(bo);
if (fb) {
- p->fb = fb;
+ drm->fb = fb;
return;
}
fb = talloc_zero(ctx, struct framebuffer);
- fb->fd = p->kms->fd;
+ fb->fd = drm->fd;
fb->width = gbm_bo_get_width(bo);
fb->height = gbm_bo_get_height(bo);
uint64_t modifier = gbm_bo_get_modifier(bo);
@@ -335,210 +313,37 @@ static void update_framebuffer_from_bo(struct ra_ctx *ctx, struct gbm_bo *bo)
MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno));
}
gbm_bo_set_user_data(bo, fb, framebuffer_destroy_callback);
- p->fb = fb;
-}
-
-static bool crtc_setup(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
- if (p->active)
- return true;
- p->active = true;
-
- struct drm_atomic_context *atomic_ctx = p->kms->atomic_context;
-
- if (!drm_atomic_save_old_state(atomic_ctx)) {
- MP_WARN(ctx->vo, "Failed to save old DRM atomic state\n");
- }
-
- drmModeAtomicReqPtr request = drmModeAtomicAlloc();
- if (!request) {
- MP_ERR(ctx->vo, "Failed to allocate drm atomic request\n");
- return false;
- }
-
- if (drm_object_set_property(request, atomic_ctx->connector, "CRTC_ID", p->kms->crtc_id) < 0) {
- MP_ERR(ctx->vo, "Could not set CRTC_ID on connector\n");
- return false;
- }
-
- if (!drm_mode_ensure_blob(p->kms->fd, &p->kms->mode)) {
- MP_ERR(ctx->vo, "Failed to create DRM mode blob\n");
- goto err;
- }
- if (drm_object_set_property(request, atomic_ctx->crtc, "MODE_ID", p->kms->mode.blob_id) < 0) {
- MP_ERR(ctx->vo, "Could not set MODE_ID on crtc\n");
- goto err;
- }
- if (drm_object_set_property(request, atomic_ctx->crtc, "ACTIVE", 1) < 0) {
- MP_ERR(ctx->vo, "Could not set ACTIVE on crtc\n");
- goto err;
- }
-
- /*
- * VRR related properties were added in kernel 5.0. We will not fail if we
- * cannot query or set the value, but we will log as appropriate.
- */
- uint64_t vrr_capable = 0;
- drm_object_get_property(atomic_ctx->connector, "VRR_CAPABLE", &vrr_capable);
- MP_VERBOSE(ctx->vo, "crtc is%s VRR capable\n", vrr_capable ? "" : " not");
-
- uint64_t vrr_requested = ctx->vo->opts->drm_opts->drm_vrr_enabled;
- if (vrr_requested == 1 || (vrr_capable && vrr_requested == -1)) {
- if (drm_object_set_property(request, atomic_ctx->crtc, "VRR_ENABLED", 1) < 0) {
- MP_WARN(ctx->vo, "Could not enable VRR on crtc\n");
- } else {
- MP_VERBOSE(ctx->vo, "Enabled VRR on crtc\n");
- }
- }
-
- drm_object_set_property(request, atomic_ctx->draw_plane, "FB_ID", p->fb->id);
- drm_object_set_property(request, atomic_ctx->draw_plane, "CRTC_ID", p->kms->crtc_id);
- drm_object_set_property(request, atomic_ctx->draw_plane, "SRC_X", 0);
- drm_object_set_property(request, atomic_ctx->draw_plane, "SRC_Y", 0);
- drm_object_set_property(request, atomic_ctx->draw_plane, "SRC_W", p->draw_surface_size.width << 16);
- drm_object_set_property(request, atomic_ctx->draw_plane, "SRC_H", p->draw_surface_size.height << 16);
- drm_object_set_property(request, atomic_ctx->draw_plane, "CRTC_X", 0);
- drm_object_set_property(request, atomic_ctx->draw_plane, "CRTC_Y", 0);
- drm_object_set_property(request, atomic_ctx->draw_plane, "CRTC_W", p->kms->mode.mode.hdisplay);
- drm_object_set_property(request, atomic_ctx->draw_plane, "CRTC_H", p->kms->mode.mode.vdisplay);
-
- int ret = drmModeAtomicCommit(p->kms->fd, request, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
- if (ret)
- MP_ERR(ctx->vo, "Failed to commit ModeSetting atomic request (%d)\n", ret);
-
- drmModeAtomicFree(request);
- return ret == 0;
-
- err:
- drmModeAtomicFree(request);
- return false;
-}
-
-static void crtc_release(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
- if (!p->active)
- return;
- p->active = false;
-
- if (!p->kms->atomic_context->old_state.saved)
- return;
-
- bool success = true;
- struct drm_atomic_context *atomic_ctx = p->kms->atomic_context;
- drmModeAtomicReqPtr request = drmModeAtomicAlloc();
- if (!request) {
- MP_ERR(ctx->vo, "Failed to allocate drm atomic request\n");
- success = false;
- }
-
- if (request && !drm_atomic_restore_old_state(request, atomic_ctx)) {
- MP_WARN(ctx->vo, "Got error while restoring old state\n");
- success = false;
- }
-
- if (request) {
- int ret = drmModeAtomicCommit(p->kms->fd, request,
- DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
- success = ret == 0;
- if (!success)
- MP_WARN(ctx->vo, "Failed to commit ModeSetting atomic request (%d)\n", ret);
- }
-
- if (request)
- drmModeAtomicFree(request);
-
- if (!success)
- MP_ERR(ctx->vo, "Failed to restore previous mode\n");
-}
-
-static void release_vt(void *data)
-{
- struct ra_ctx *ctx = data;
- MP_VERBOSE(ctx->vo, "Releasing VT\n");
- crtc_release(ctx);
-
- const 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 ra_ctx *ctx = data;
- MP_VERBOSE(ctx->vo, "Acquiring VT\n");
-
- const 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);
+ drm->fb = fb;
}
static void queue_flip(struct ra_ctx *ctx, struct gbm_frame *frame)
{
- struct priv *p = ctx->priv;
- struct drm_atomic_context *atomic_ctx = p->kms->atomic_context;
- int ret;
+ struct vo_drm_state *drm = ctx->vo->drm;
update_framebuffer_from_bo(ctx, frame->bo);
- // Alloc and fill the data struct for the page flip callback
- struct drm_pflip_cb_closure *data = talloc(ctx, struct drm_pflip_cb_closure);
- data->frame_vsync = &frame->vsync;
- data->vsync = &p->vsync;
- data->vsync_info = &p->vsync_info;
- data->waiting_for_flip = &p->waiting_for_flip;
- data->log = ctx->log;
-
- drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "FB_ID", p->fb->id);
+ struct drm_atomic_context *atomic_ctx = drm->atomic_context;
+ drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "FB_ID", drm->fb->id);
drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "CRTC_ID", atomic_ctx->crtc->id);
drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "ZPOS", 1);
- ret = drmModeAtomicCommit(p->kms->fd, atomic_ctx->request,
- DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, data);
- if (ret) {
- MP_WARN(ctx->vo, "Failed to commit atomic request (%d)\n", ret);
- talloc_free(data);
- }
- p->waiting_for_flip = !ret;
+ int ret = drmModeAtomicCommit(drm->fd, atomic_ctx->request,
+ DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, drm);
+
+ if (ret)
+ MP_WARN(ctx->vo, "Failed to commit atomic request: %s\n", mp_strerror(ret));
+ drm->waiting_for_flip = !ret;
drmModeAtomicFree(atomic_ctx->request);
atomic_ctx->request = drmModeAtomicAlloc();
}
-static void wait_on_flip(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
-
- // poll page flip finish event
- while (p->waiting_for_flip) {
- 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) {
- const int ret = drmHandleEvent(p->kms->fd, &p->ev);
- if (ret != 0) {
- MP_ERR(ctx->vo, "drmHandleEvent failed: %i\n", ret);
- return;
- }
- }
- }
-}
-
static void enqueue_bo(struct ra_ctx *ctx, struct gbm_bo *bo)
{
struct priv *p = ctx->priv;
- p->vsync.sbc++;
struct gbm_frame *new_frame = talloc(p, struct gbm_frame);
new_frame->bo = bo;
- new_frame->vsync = p->vsync;
MP_TARRAY_APPEND(p, p->gbm.bo_queue, p->gbm.num_bos, new_frame);
}
@@ -588,10 +393,11 @@ static bool drm_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
{
struct ra_ctx *ctx = sw->ctx;
struct priv *p = ctx->priv;
+ struct vo_drm_state *drm = ctx->vo->drm;
- if (!p->kms->atomic_context->request) {
- p->kms->atomic_context->request = drmModeAtomicAlloc();
- p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request;
+ if (!drm->atomic_context->request) {
+ drm->atomic_context->request = drmModeAtomicAlloc();
+ p->drm_params.atomic_request_ptr = &drm->atomic_context->request;
}
return ra_gl_ctx_start_frame(sw, out_fbo);
@@ -600,9 +406,9 @@ static bool drm_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
static bool drm_egl_submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
{
struct ra_ctx *ctx = sw->ctx;
- struct priv *p = ctx->priv;
+ struct vo_drm_state *drm = ctx->vo->drm;
- p->still = frame->still;
+ drm->still = frame->still;
return ra_gl_ctx_submit_frame(sw, frame);
}
@@ -611,9 +417,10 @@ static void drm_egl_swap_buffers(struct ra_swapchain *sw)
{
struct ra_ctx *ctx = sw->ctx;
struct priv *p = ctx->priv;
- const bool drain = p->paused || p->still; // True when we need to drain the swapchain
+ struct vo_drm_state *drm = ctx->vo->drm;
+ const bool drain = drm->paused || drm->still; // True when we need to drain the swapchain
- if (!p->active)
+ if (!drm->active)
return;
wait_fence(ctx);
@@ -630,8 +437,8 @@ static void drm_egl_swap_buffers(struct ra_swapchain *sw)
while (drain || p->gbm.num_bos > ctx->vo->opts->swapchain_depth ||
!gbm_surface_has_free_buffers(p->gbm.surface)) {
- if (p->waiting_for_flip) {
- wait_on_flip(ctx);
+ if (drm->waiting_for_flip) {
+ vo_drm_wait_on_flip(drm);
swapchain_step(ctx);
}
if (p->gbm.num_bos <= 1)
@@ -654,40 +461,41 @@ static const struct ra_swapchain_fns drm_egl_swapchain = {
static void drm_egl_uninit(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
- struct drm_atomic_context *atomic_ctx = p->kms->atomic_context;
+ struct vo_drm_state *drm = ctx->vo->drm;
+ if (drm) {
+ struct drm_atomic_context *atomic_ctx = drm->atomic_context;
- int ret = drmModeAtomicCommit(p->kms->fd, atomic_ctx->request, 0, NULL);
- if (ret)
- MP_ERR(ctx->vo, "Failed to commit atomic request (%d)\n", ret);
- drmModeAtomicFree(atomic_ctx->request);
-
- ra_gl_ctx_uninit(ctx);
+ if (drmModeAtomicCommit(drm->fd, atomic_ctx->request, 0, NULL))
+ MP_ERR(ctx->vo, "Failed to commit atomic request: %s\n",
+ mp_strerror(errno));
- crtc_release(ctx);
- if (p->vt_switcher_active)
- vt_switcher_destroy(&p->vt_switcher);
-
- // According to GBM documentation all BO:s must be released before
- // gbm_surface_destroy can be called on the surface.
- while (p->gbm.num_bos) {
- swapchain_step(ctx);
+ drmModeAtomicFree(atomic_ctx->request);
}
- 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);
+ ra_gl_ctx_uninit(ctx);
+ vo_drm_uninit(ctx->vo);
+
+ if (p) {
+ // According to GBM documentation all BO:s must be released
+ // before gbm_surface_destroy can be called on the surface.
+ while (p->gbm.num_bos) {
+ swapchain_step(ctx);
+ }
- close(p->drm_params.render_fd);
+ eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ if (p->egl.display != EGL_NO_DISPLAY) {
+ eglDestroySurface(p->egl.display, p->egl.surface);
+ eglDestroyContext(p->egl.display, p->egl.context);
+ }
+ if (p->gbm.surface)
+ gbm_surface_destroy(p->gbm.surface);
+ eglTerminate(p->egl.display);
+ if (p->gbm.device)
+ gbm_device_destroy(p->gbm.device);
- if (p->kms) {
- kms_destroy(p->kms);
- p->kms = 0;
+ if (p->drm_params.render_fd != -1)
+ close(p->drm_params.render_fd);
}
}
@@ -699,9 +507,9 @@ static void drm_egl_uninit(struct ra_ctx *ctx)
static bool probe_gbm_format(struct ra_ctx *ctx, uint32_t argb_format, uint32_t xrgb_format)
{
struct priv *p = ctx->priv;
+ struct vo_drm_state *drm = ctx->vo->drm;
- drmModePlane *drmplane =
- drmModeGetPlane(p->kms->fd, p->kms->atomic_context->draw_plane->id);
+ drmModePlane *drmplane = drmModeGetPlane(drm->fd, drm->atomic_context->draw_plane->id);
bool have_argb = false;
bool have_xrgb = false;
bool result = false;
@@ -731,9 +539,10 @@ static bool probe_gbm_format(struct ra_ctx *ctx, uint32_t argb_format, uint32_t
static bool probe_gbm_modifiers(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+ struct vo_drm_state *drm = ctx->vo->drm;
- drmModePropertyBlobPtr blob =
- drm_object_get_property_blob(p->kms->atomic_context->draw_plane, "IN_FORMATS");
+ drmModePropertyBlobPtr blob = drm_object_get_property_blob(drm->atomic_context->draw_plane,
+ "IN_FORMATS");
if (!blob) {
MP_VERBOSE(ctx->vo, "Failed to find IN_FORMATS property\n");
return false;
@@ -769,47 +578,32 @@ static bool probe_gbm_modifiers(struct ra_ctx *ctx)
static void drm_egl_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info)
{
- struct priv *p = ctx->priv;
- *info = p->vsync_info;
+ struct vo_drm_state *drm = ctx->vo->drm;
+ present_sync_get_info(drm->present, info);
}
static bool drm_egl_init(struct ra_ctx *ctx)
{
+ if (!vo_drm_init(ctx->vo))
+ goto err;
+
struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
- p->ev.version = DRM_EVENT_CONTEXT_VERSION;
- p->ev.page_flip_handler = &drm_pflip_cb;
+ struct vo_drm_state *drm = ctx->vo->drm;
- 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);
+ if (ctx->vo->drm->opts->draw_surface_size.wh_valid) {
+ p->draw_surface_size.width = ctx->vo->drm->opts->draw_surface_size.w;
+ p->draw_surface_size.height = ctx->vo->drm->opts->draw_surface_size.h;
} else {
- MP_WARN(ctx, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
- }
-
- MP_VERBOSE(ctx, "Initializing KMS\n");
- p->kms = kms_create(ctx->log,
- ctx->vo->opts->drm_opts->drm_device_path,
- ctx->vo->opts->drm_opts->drm_connector_spec,
- ctx->vo->opts->drm_opts->drm_mode_spec,
- ctx->vo->opts->drm_opts->drm_draw_plane,
- ctx->vo->opts->drm_opts->drm_drmprime_video_plane);
- if (!p->kms) {
- MP_ERR(ctx, "Failed to create KMS.\n");
- return false;
+ p->draw_surface_size.width = drm->mode.mode.hdisplay;
+ p->draw_surface_size.height = drm->mode.mode.vdisplay;
}
- if (ctx->vo->opts->drm_opts->drm_draw_surface_size.wh_valid) {
- p->draw_surface_size.width = ctx->vo->opts->drm_opts->drm_draw_surface_size.w;
- p->draw_surface_size.height = ctx->vo->opts->drm_opts->drm_draw_surface_size.h;
- } else {
- p->draw_surface_size.width = p->kms->mode.mode.hdisplay;
- p->draw_surface_size.height = p->kms->mode.mode.vdisplay;
- }
+ drm->width = p->draw_surface_size.width;
+ drm->height = p->draw_surface_size.height;
uint32_t argb_format;
uint32_t xrgb_format;
- switch (ctx->vo->opts->drm_opts->drm_format) {
+ switch (ctx->vo->drm->opts->drm_format) {
case DRM_OPTS_FORMAT_XRGB2101010:
argb_format = GBM_FORMAT_ARGB2101010;
xrgb_format = GBM_FORMAT_XRGB2101010;
@@ -823,6 +617,10 @@ static bool drm_egl_init(struct ra_ctx *ctx)
xrgb_format = GBM_FORMAT_XBGR8888;
break;
default:
+ if (drm->opts->drm_format != DRM_OPTS_FORMAT_XRGB8888) {
+ MP_VERBOSE(ctx->vo, "Requested format not supported by context, "
+ "falling back to xrgb8888\n");
+ }
argb_format = GBM_FORMAT_ARGB8888;
xrgb_format = GBM_FORMAT_XRGB8888;
break;
@@ -831,7 +629,7 @@ static bool drm_egl_init(struct ra_ctx *ctx)
if (!probe_gbm_format(ctx, argb_format, xrgb_format)) {
MP_ERR(ctx->vo, "No suitable format found on draw plane (tried: %s and %s).\n",
gbm_format_to_string(argb_format), gbm_format_to_string(xrgb_format));
- return false;
+ goto err;
}
// It is not fatal if this fails. We'll just try without modifiers.
@@ -839,18 +637,18 @@ static bool drm_egl_init(struct ra_ctx *ctx)
if (!init_gbm(ctx)) {
MP_ERR(ctx->vo, "Failed to setup GBM.\n");
- return false;
+ goto err;
}
if (!init_egl(ctx)) {
MP_ERR(ctx->vo, "Failed to setup EGL.\n");
- return false;
+ goto err;
}
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 false;
+ goto err;
}
mpegl_load_functions(&p->gl, ctx->vo->log);
@@ -861,38 +659,39 @@ static bool drm_egl_init(struct ra_ctx *ctx)
struct gbm_bo *new_bo = gbm_surface_lock_front_buffer(p->gbm.surface);
if (!new_bo) {
MP_ERR(ctx, "Failed to lock GBM surface.\n");
- return false;
+ goto err;
}
enqueue_bo(ctx, new_bo);
update_framebuffer_from_bo(ctx, new_bo);
- if (!p->fb || !p->fb->id) {
+ if (!drm->fb || !drm->fb->id) {
MP_ERR(ctx, "Failed to create framebuffer.\n");
- return false;
+ goto err;
}
- if (!crtc_setup(ctx)) {
+ if (!vo_drm_acquire_crtc(ctx->vo->drm)) {
MP_ERR(ctx, "Failed to set CRTC for connector %u: %s\n",
- p->kms->connector->connector_id, mp_strerror(errno));
- return false;
+ drm->connector->connector_id, mp_strerror(errno));
+ goto err;
}
- p->drm_params.fd = p->kms->fd;
- p->drm_params.crtc_id = p->kms->crtc_id;
- p->drm_params.connector_id = p->kms->connector->connector_id;
- p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request;
- char *rendernode_path = drmGetRenderDeviceNameFromFd(p->kms->fd);
+ vo_drm_set_monitor_par(ctx->vo);
+
+ p->drm_params.fd = drm->fd;
+ p->drm_params.crtc_id = drm->crtc_id;
+ p->drm_params.connector_id = drm->connector->connector_id;
+ p->drm_params.atomic_request_ptr = &drm->atomic_context->request;
+ char *rendernode_path = drmGetRenderDeviceNameFromFd(drm->fd);
if (rendernode_path) {
MP_VERBOSE(ctx, "Opening render node \"%s\"\n", rendernode_path);
p->drm_params.render_fd = open(rendernode_path, O_RDWR | O_CLOEXEC);
if (p->drm_params.render_fd == -1) {
- MP_WARN(ctx, "Cannot open render node \"%s\": %s. VAAPI hwdec will be disabled\n",
- rendernode_path, mp_strerror(errno));
+ MP_WARN(ctx, "Cannot open render node: %s\n", mp_strerror(errno));
}
free(rendernode_path);
} else {
p->drm_params.render_fd = -1;
- MP_VERBOSE(ctx, "Could not find path to render node. VAAPI hwdec will be disabled\n");
+ MP_VERBOSE(ctx, "Could not find path to render node.\n");
}
struct ra_gl_ctx_params params = {
@@ -900,94 +699,52 @@ static bool drm_egl_init(struct ra_ctx *ctx)
.get_vsync = &drm_egl_get_vsync,
};
if (!ra_gl_ctx_init(ctx, &p->gl, params))
- return false;
+ goto err;
ra_add_native_resource(ctx->ra, "drm_params_v2", &p->drm_params);
ra_add_native_resource(ctx->ra, "drm_draw_surface_size", &p->draw_surface_size);
- if (ctx->vo->opts->force_monitor_aspect != 0.0) {
- ctx->vo->monitor_par = p->fb->width / (double) p->fb->height /
- ctx->vo->opts->force_monitor_aspect;
- } else {
- ctx->vo->monitor_par = 1 / ctx->vo->opts->monitor_pixel_aspect;
- }
-
- mp_verbose(ctx->vo->log, "Monitor pixel aspect: %g\n", ctx->vo->monitor_par);
-
- p->vsync_info.vsync_duration = 0;
- p->vsync_info.skipped_vsyncs = -1;
- p->vsync_info.last_queue_display_time = -1;
-
return true;
+
+err:
+ drm_egl_uninit(ctx);
+ return false;
}
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;
- ra_gl_ctx_resize(ctx->swapchain, p->fb->width, p->fb->height, 0);
+ struct vo_drm_state *drm = ctx->vo->drm;
+ ctx->vo->dwidth = drm->fb->width;
+ ctx->vo->dheight = drm->fb->height;
+ ra_gl_ctx_resize(ctx->swapchain, drm->fb->width, drm->fb->height, 0);
return true;
}
static int drm_egl_control(struct ra_ctx *ctx, int *events, int request,
void *arg)
{
- struct priv *p = ctx->priv;
- switch (request) {
- case VOCTRL_GET_DISPLAY_FPS: {
- double fps = kms_get_display_fps(p->kms);
- if (fps <= 0)
- break;
- *(double*)arg = fps;
- return VO_TRUE;
- }
- case VOCTRL_GET_DISPLAY_RES: {
- ((int *)arg)[0] = p->kms->mode.mode.hdisplay;
- ((int *)arg)[1] = p->kms->mode.mode.vdisplay;
- return VO_TRUE;
- }
- case VOCTRL_PAUSE:
- ctx->vo->want_redraw = true;
- p->paused = true;
- return VO_TRUE;
- case VOCTRL_RESUME:
- p->paused = false;
- p->vsync_info.last_queue_display_time = -1;
- p->vsync_info.skipped_vsyncs = 0;
- p->vsync.ust = 0;
- p->vsync.msc = 0;
- return VO_TRUE;
- }
- return VO_NOTIMPL;
+ int ret = vo_drm_control(ctx->vo, events, request, arg);
+ return ret;
}
-static void wait_events(struct ra_ctx *ctx, int64_t until_time_us)
+static void drm_egl_wait_events(struct ra_ctx *ctx, int64_t until_time_ns)
{
- struct priv *p = ctx->priv;
- if (p->vt_switcher_active) {
- int64_t wait_us = until_time_us - mp_time_us();
- int timeout_ms = MPCLAMP((wait_us + 500) / 1000, 0, 10000);
- vt_switcher_poll(&p->vt_switcher, timeout_ms);
- } else {
- vo_wait_default(ctx->vo, until_time_us);
- }
+ vo_drm_wait_events(ctx->vo, until_time_ns);
}
-static void wakeup(struct ra_ctx *ctx)
+static void drm_egl_wakeup(struct ra_ctx *ctx)
{
- struct priv *p = ctx->priv;
- if (p->vt_switcher_active)
- vt_switcher_interrupt_poll(&p->vt_switcher);
+ vo_drm_wakeup(ctx->vo);
}
const struct ra_ctx_fns ra_ctx_drm_egl = {
.type = "opengl",
.name = "drm",
+ .description = "DRM/EGL",
.reconfig = drm_egl_reconfig,
.control = drm_egl_control,
.init = drm_egl_init,
.uninit = drm_egl_uninit,
- .wait_events = wait_events,
- .wakeup = wakeup,
+ .wait_events = drm_egl_wait_events,
+ .wakeup = drm_egl_wakeup,
};