summaryrefslogtreecommitdiffstats
path: root/video/out/vo_drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/vo_drm.c')
-rw-r--r--video/out/vo_drm.c539
1 files changed, 154 insertions, 385 deletions
diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c
index a2c6fc8652..34726a3c02 100644
--- a/video/out/vo_drm.c
+++ b/video/out/vo_drm.c
@@ -24,73 +24,40 @@
#include <unistd.h>
#include <drm_fourcc.h>
-#include <libswscale/swscale.h>
-
-#include "drm_common.h"
#include "common/msg.h"
+#include "drm_atomic.h"
+#include "drm_common.h"
#include "osdep/timer.h"
#include "sub/osd.h"
#include "video/fmt-conversion.h"
#include "video/mp_image.h"
+#include "video/out/present_sync.h"
#include "video/sws_utils.h"
#include "vo.h"
#define IMGFMT_XRGB8888 IMGFMT_BGR0
-#if BYTE_ORDER == BIG_ENDIAN
-#define IMGFMT_XRGB2101010 pixfmt2imgfmt(AV_PIX_FMT_GBRP10BE)
-#else
-#define IMGFMT_XRGB2101010 pixfmt2imgfmt(AV_PIX_FMT_GBRP10LE)
-#endif
+#define IMGFMT_XBGR8888 IMGFMT_RGB0
+#define IMGFMT_XRGB2101010 \
+ pixfmt2imgfmt(MP_SELECT_LE_BE(AV_PIX_FMT_X2RGB10LE, AV_PIX_FMT_X2RGB10BE))
+#define IMGFMT_XBGR2101010 \
+ pixfmt2imgfmt(MP_SELECT_LE_BE(AV_PIX_FMT_X2BGR10LE, AV_PIX_FMT_X2BGR10BE))
+#define IMGFMT_YUYV pixfmt2imgfmt(AV_PIX_FMT_YUYV422)
#define BYTES_PER_PIXEL 4
#define BITS_PER_PIXEL 32
-#define USE_MASTER 0
-
-struct framebuffer {
- uint32_t width;
- uint32_t height;
- uint32_t stride;
- uint32_t size;
- uint32_t handle;
- uint8_t *map;
- uint32_t fb;
-};
-struct kms_frame {
+struct drm_frame {
struct framebuffer *fb;
- struct drm_vsync_tuple vsync;
};
struct priv {
- char *connector_spec;
- int mode_id;
-
- struct kms *kms;
- drmModeCrtc *old_crtc;
- drmEventContext ev;
-
- bool vt_switcher_active;
- struct vt_switcher vt_switcher;
-
- int swapchain_depth;
- unsigned int buf_count;
- struct framebuffer *bufs;
- int front_buf;
- bool active;
- bool waiting_for_flip;
- bool still;
- bool paused;
-
- struct kms_frame **fb_queue;
+ struct drm_frame **fb_queue;
unsigned int fb_queue_len;
- struct framebuffer *cur_fb;
uint32_t drm_format;
enum mp_imgfmt imgfmt;
- int32_t screen_w;
- int32_t screen_h;
struct mp_image *last_input;
struct mp_image *cur_frame;
struct mp_image *cur_frame_cropped;
@@ -99,53 +66,92 @@ struct priv {
struct mp_osd_res osd;
struct mp_sws_context *sws;
- struct drm_vsync_tuple vsync;
- struct vo_vsync_info vsync_info;
+ struct framebuffer **bufs;
+ int front_buf;
+ int buf_count;
};
-static void fb_destroy(int fd, struct framebuffer *buf)
+static void destroy_framebuffer(int fd, struct framebuffer *fb)
{
- if (buf->map) {
- munmap(buf->map, buf->size);
+ if (!fb)
+ return;
+
+ if (fb->map) {
+ munmap(fb->map, fb->size);
}
- if (buf->fb) {
- drmModeRmFB(fd, buf->fb);
+ if (fb->id) {
+ drmModeRmFB(fd, fb->id);
}
- if (buf->handle) {
+ if (fb->handle) {
struct drm_mode_destroy_dumb dreq = {
- .handle = buf->handle,
+ .handle = fb->handle,
};
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
}
}
-static bool fb_setup_single(struct vo *vo, int fd, struct framebuffer *buf)
+static struct framebuffer *setup_framebuffer(struct vo *vo)
{
struct priv *p = vo->priv;
+ struct vo_drm_state *drm = vo->drm;
- buf->handle = 0;
+ struct framebuffer *fb = talloc_zero(drm, struct framebuffer);
+ fb->width = drm->mode.mode.hdisplay;
+ fb->height = drm->mode.mode.vdisplay;
+ fb->fd = drm->fd;
+ fb->handle = 0;
// create dumb buffer
struct drm_mode_create_dumb creq = {
- .width = buf->width,
- .height = buf->height,
+ .width = fb->width,
+ .height = fb->height,
.bpp = BITS_PER_PIXEL,
};
- if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq) < 0) {
+
+ if (drmIoctl(drm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq) < 0) {
MP_ERR(vo, "Cannot create dumb buffer: %s\n", mp_strerror(errno));
goto err;
}
- buf->stride = creq.pitch;
- buf->size = creq.size;
- buf->handle = creq.handle;
+
+ fb->stride = creq.pitch;
+ fb->size = creq.size;
+ fb->handle = creq.handle;
+
+ // select format
+ switch (drm->opts->drm_format) {
+ case DRM_OPTS_FORMAT_XRGB2101010:
+ p->drm_format = DRM_FORMAT_XRGB2101010;
+ p->imgfmt = IMGFMT_XRGB2101010;
+ break;
+ case DRM_OPTS_FORMAT_XBGR2101010:
+ p->drm_format = DRM_FORMAT_XRGB2101010;
+ p->imgfmt = IMGFMT_XRGB2101010;
+ break;
+ case DRM_OPTS_FORMAT_XBGR8888:
+ p->drm_format = DRM_FORMAT_XBGR8888;
+ p->imgfmt = IMGFMT_XBGR8888;
+ break;
+ case DRM_OPTS_FORMAT_YUYV:
+ p->drm_format = DRM_FORMAT_YUYV;
+ p->imgfmt = IMGFMT_YUYV;
+ break;
+ default:
+ if (drm->opts->drm_format != DRM_OPTS_FORMAT_XRGB8888) {
+ MP_VERBOSE(vo, "Requested format not supported by VO, "
+ "falling back to xrgb8888\n");
+ }
+ p->drm_format = DRM_FORMAT_XRGB8888;
+ p->imgfmt = IMGFMT_XRGB8888;
+ break;
+ }
// create framebuffer object for the dumb-buffer
- int ret = drmModeAddFB2(fd, buf->width, buf->height,
+ int ret = drmModeAddFB2(fb->fd, fb->width, fb->height,
p->drm_format,
- (uint32_t[4]){buf->handle, 0, 0, 0},
- (uint32_t[4]){buf->stride, 0, 0, 0},
+ (uint32_t[4]){fb->handle, 0, 0, 0},
+ (uint32_t[4]){fb->stride, 0, 0, 0},
(uint32_t[4]){0, 0, 0, 0},
- &buf->fb, 0);
+ &fb->id, 0);
if (ret) {
MP_ERR(vo, "Cannot create framebuffer: %s\n", mp_strerror(errno));
goto err;
@@ -153,176 +159,56 @@ static bool fb_setup_single(struct vo *vo, int fd, struct framebuffer *buf)
// prepare buffer for memory mapping
struct drm_mode_map_dumb mreq = {
- .handle = buf->handle,
+ .handle = fb->handle,
};
- if (drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) {
+ if (drmIoctl(drm->fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) {
MP_ERR(vo, "Cannot map dumb buffer: %s\n", mp_strerror(errno));
goto err;
}
// perform actual memory mapping
- buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
- fd, mreq.offset);
- if (buf->map == MAP_FAILED) {
+ fb->map = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ drm->fd, mreq.offset);
+ if (fb->map == MAP_FAILED) {
MP_ERR(vo, "Cannot map dumb buffer: %s\n", mp_strerror(errno));
goto err;
}
- memset(buf->map, 0, buf->size);
- return true;
+ memset(fb->map, 0, fb->size);
+ return fb;
err:
- fb_destroy(fd, buf);
- return false;
-}
-
-static bool fb_setup_buffers(struct vo *vo)
-{
- struct priv *p = vo->priv;
-
- p->bufs = talloc_zero_array(p, struct framebuffer, p->buf_count);
-
- p->front_buf = 0;
- for (unsigned int i = 0; i < p->buf_count; i++) {
- p->bufs[i].width = p->kms->mode.mode.hdisplay;
- p->bufs[i].height = p->kms->mode.mode.vdisplay;
- }
-
- for (unsigned int i = 0; i < p->buf_count; i++) {
- if (!fb_setup_single(vo, p->kms->fd, &p->bufs[i])) {
- MP_ERR(vo, "Cannot create framebuffer\n");
- for (unsigned int j = 0; j < i; j++) {
- fb_destroy(p->kms->fd, &p->bufs[j]);
- }
- return false;
- }
- }
-
- p->cur_fb = &p->bufs[0];
-
- return true;
-}
-
-static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
-{
- struct priv *p = vo->priv;
- *info = p->vsync_info;
-}
-
-static bool crtc_setup(struct vo *vo)
-{
- struct priv *p = vo->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->cur_fb->fb,
- 0, 0, &p->kms->connector->connector_id, 1,
- &p->kms->mode.mode);
- p->active = true;
- return ret == 0;
-}
-
-static void crtc_release(struct vo *vo)
-{
- struct priv *p = vo->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(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 vo *vo = data;
- crtc_release(vo);
- 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 = vo->priv;
- if (drmDropMaster(p->kms->fd)) {
- MP_WARN(vo, "Failed to drop DRM master: %s\n", mp_strerror(errno));
- }
- }
-}
-
-static void acquire_vt(void *data)
-{
- struct vo *vo = data;
- if (USE_MASTER) {
- struct priv *p = vo->priv;
- if (drmSetMaster(p->kms->fd)) {
- MP_WARN(vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno));
- }
- }
-
- crtc_setup(vo);
-}
-
-static void wait_events(struct vo *vo, int64_t until_time_us)
-{
- struct priv *p = vo->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(vo, until_time_us);
- }
-}
-
-static void wakeup(struct vo *vo)
-{
- struct priv *p = vo->priv;
- if (p->vt_switcher_active)
- vt_switcher_interrupt_poll(&p->vt_switcher);
+ destroy_framebuffer(drm->fd, fb);
+ return NULL;
}
static int reconfig(struct vo *vo, struct mp_image_params *params)
{
struct priv *p = vo->priv;
+ struct vo_drm_state *drm = vo->drm;
- vo->dwidth = p->screen_w;
- vo->dheight = p->screen_h;
+ vo->dwidth =drm->fb->width;
+ vo->dheight = drm->fb->height;
vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);
- int w = p->dst.x1 - p->dst.x0;
- int h = p->dst.y1 - p->dst.y0;
+ struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(p->imgfmt);
+ p->dst.x0 = MP_ALIGN_DOWN(p->dst.x0, fmt.align_x);
+ p->dst.y0 = MP_ALIGN_DOWN(p->dst.y0, fmt.align_y);
p->sws->src = *params;
p->sws->dst = (struct mp_image_params) {
.imgfmt = p->imgfmt,
- .w = w,
- .h = h,
+ .w = mp_rect_w(p->dst),
+ .h = mp_rect_h(p->dst),
.p_w = 1,
.p_h = 1,
};
talloc_free(p->cur_frame);
- p->cur_frame = mp_image_alloc(p->imgfmt, p->screen_w, p->screen_h);
+ p->cur_frame = mp_image_alloc(p->imgfmt, drm->fb->width, drm->fb->height);
mp_image_params_guess_csp(&p->sws->dst);
mp_image_set_params(p->cur_frame, &p->sws->dst);
- mp_image_set_size(p->cur_frame, p->screen_w, p->screen_h);
+ mp_image_set_size(p->cur_frame, drm->fb->width, drm->fb->height);
talloc_free(p->cur_frame_cropped);
p->cur_frame_cropped = mp_image_new_dummy_ref(p->cur_frame);
@@ -334,33 +220,13 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
if (mp_sws_reinit(p->sws) < 0)
return -1;
- p->vsync_info.vsync_duration = 0;
- p->vsync_info.skipped_vsyncs = -1;
- p->vsync_info.last_queue_display_time = -1;
-
+ mp_mutex_lock(&vo->params_mutex);
+ vo->target_params = &p->sws->dst; // essentially constant, so this is okay
+ mp_mutex_unlock(&vo->params_mutex);
vo->want_redraw = true;
return 0;
}
-static void wait_on_flip(struct vo *vo)
-{
- struct priv *p = vo->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(vo, "drmHandleEvent failed: %i\n", ret);
- return;
- }
- }
- }
-}
-
static struct framebuffer *get_new_fb(struct vo *vo)
{
struct priv *p = vo->priv;
@@ -368,14 +234,15 @@ static struct framebuffer *get_new_fb(struct vo *vo)
p->front_buf++;
p->front_buf %= p->buf_count;
- return &p->bufs[p->front_buf];
+ return p->bufs[p->front_buf];
}
-static void draw_image(struct vo *vo, mp_image_t *mpi, struct framebuffer *front_buf)
+static void draw_image(struct vo *vo, mp_image_t *mpi, struct framebuffer *buf)
{
struct priv *p = vo->priv;
+ struct vo_drm_state *drm = vo->drm;
- if (p->active && front_buf != NULL) {
+ if (drm->active && buf != NULL) {
if (mpi) {
struct mp_image src = *mpi;
struct mp_rect src_rc = p->src;
@@ -395,35 +262,10 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, struct framebuffer *front
osd_draw_on_image(vo->osd, p->osd, 0, 0, p->cur_frame);
}
- if (p->drm_format == DRM_FORMAT_XRGB2101010) {
- // Pack GBRP10 image into XRGB2101010 for DRM
- const int w = p->cur_frame->w;
- const int h = p->cur_frame->h;
-
- const int g_padding = p->cur_frame->stride[0]/sizeof(uint16_t) - w;
- const int b_padding = p->cur_frame->stride[1]/sizeof(uint16_t) - w;
- const int r_padding = p->cur_frame->stride[2]/sizeof(uint16_t) - w;
- const int fbuf_padding = front_buf->stride/sizeof(uint32_t) - w;
-
- uint16_t *g_ptr = (uint16_t*)p->cur_frame->planes[0];
- uint16_t *b_ptr = (uint16_t*)p->cur_frame->planes[1];
- uint16_t *r_ptr = (uint16_t*)p->cur_frame->planes[2];
- uint32_t *fbuf_ptr = (uint32_t*)front_buf->map;
- for (unsigned y = 0; y < h; ++y) {
- for (unsigned x = 0; x < w; ++x) {
- *fbuf_ptr++ = (*r_ptr++ << 20) | (*g_ptr++ << 10) | (*b_ptr++);
- }
- g_ptr += g_padding;
- b_ptr += b_padding;
- r_ptr += r_padding;
- fbuf_ptr += fbuf_padding;
- }
- } else { // p->drm_format == DRM_FORMAT_XRGB8888
- memcpy_pic(front_buf->map, p->cur_frame->planes[0],
- p->cur_frame->w * BYTES_PER_PIXEL, p->cur_frame->h,
- front_buf->stride,
- p->cur_frame->stride[0]);
- }
+ memcpy_pic(buf->map, p->cur_frame->planes[0],
+ p->cur_frame->w * BYTES_PER_PIXEL, p->cur_frame->h,
+ buf->stride,
+ p->cur_frame->stride[0]);
}
if (mpi != p->last_input) {
@@ -436,10 +278,8 @@ static void enqueue_frame(struct vo *vo, struct framebuffer *fb)
{
struct priv *p = vo->priv;
- p->vsync.sbc++;
- struct kms_frame *new_frame = talloc(p, struct kms_frame);
+ struct drm_frame *new_frame = talloc(p, struct drm_frame);
new_frame->fb = fb;
- new_frame->vsync = p->vsync;
MP_TARRAY_APPEND(p, p->fb_queue, p->fb_queue_len, new_frame);
}
@@ -462,17 +302,17 @@ static void swapchain_step(struct vo *vo)
static void draw_frame(struct vo *vo, struct vo_frame *frame)
{
+ struct vo_drm_state *drm = vo->drm;
struct priv *p = vo->priv;
- if (!p->active)
+ if (!drm->active)
return;
- p->still = frame->still;
+ drm->still = frame->still;
// we redraw the entire image when OSD needs to be redrawn
+ struct framebuffer *fb = p->bufs[p->front_buf];
const bool repeat = frame->repeat && !frame->redraw;
-
- struct framebuffer *fb = &p->bufs[p->front_buf];
if (!repeat) {
fb = get_new_fb(vo);
draw_image(vo, mp_image_new_ref(frame->current), fb);
@@ -481,42 +321,31 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
enqueue_frame(vo, fb);
}
-static void queue_flip(struct vo *vo, struct kms_frame *frame)
+static void queue_flip(struct vo *vo, struct drm_frame *frame)
{
- int ret = 0;
- struct priv *p = vo->priv;
-
- p->cur_fb = frame->fb;
+ struct vo_drm_state *drm = vo->drm;
- // Alloc and fill the data struct for the page flip callback
- struct drm_pflip_cb_closure *data = talloc(p, 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 = vo->log;
+ drm->fb = frame->fb;
- ret = drmModePageFlip(p->kms->fd, p->kms->crtc_id,
- p->cur_fb->fb,
- DRM_MODE_PAGE_FLIP_EVENT, data);
- if (ret) {
+ int ret = drmModePageFlip(drm->fd, drm->crtc_id,
+ drm->fb->id, DRM_MODE_PAGE_FLIP_EVENT, drm);
+ if (ret)
MP_WARN(vo, "Failed to queue page flip: %s\n", mp_strerror(errno));
- } else {
- p->waiting_for_flip = true;
- }
+ drm->waiting_for_flip = !ret;
}
static void flip_page(struct vo *vo)
{
struct priv *p = vo->priv;
- const bool drain = p->paused || p->still;
+ struct vo_drm_state *drm = vo->drm;
+ const bool drain = drm->paused || drm->still;
- if (!p->active)
+ if (!drm->active)
return;
- while (drain || p->fb_queue_len > p->swapchain_depth) {
- if (p->waiting_for_flip) {
- wait_on_flip(vo);
+ while (drain || p->fb_queue_len > vo->opts->swapchain_depth) {
+ if (drm->waiting_for_flip) {
+ vo_drm_wait_on_flip(vo->drm);
swapchain_step(vo);
}
if (p->fb_queue_len <= 1)
@@ -530,26 +359,22 @@ static void flip_page(struct vo *vo)
}
}
+static void get_vsync(struct vo *vo, struct vo_vsync_info *info)
+{
+ struct vo_drm_state *drm = vo->drm;
+ present_sync_get_info(drm->present, info);
+}
+
static void uninit(struct vo *vo)
{
struct priv *p = vo->priv;
- crtc_release(vo);
+ vo_drm_uninit(vo);
while (p->fb_queue_len > 0) {
swapchain_step(vo);
}
- if (p->kms) {
- for (unsigned int i = 0; i < p->buf_count; i++)
- fb_destroy(p->kms->fd, &p->bufs[i]);
- kms_destroy(p->kms);
- p->kms = NULL;
- }
-
- if (p->vt_switcher_active)
- vt_switcher_destroy(&p->vt_switcher);
-
talloc_free(p->last_input);
talloc_free(p->cur_frame);
talloc_free(p->cur_frame_cropped);
@@ -558,72 +383,35 @@ static void uninit(struct vo *vo)
static int preinit(struct vo *vo)
{
struct priv *p = vo->priv;
- p->sws = mp_sws_alloc(vo);
- p->sws->log = vo->log;
- mp_sws_enable_cmdline_opts(p->sws, vo->global);
- p->ev.version = DRM_EVENT_CONTEXT_VERSION;
- p->ev.page_flip_handler = &drm_pflip_cb;
-
- p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, vo->log);
- if (p->vt_switcher_active) {
- vt_switcher_acquire(&p->vt_switcher, acquire_vt, vo);
- vt_switcher_release(&p->vt_switcher, release_vt, vo);
- } else {
- MP_WARN(vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
- }
- p->kms = kms_create(vo->log,
- vo->opts->drm_opts->drm_connector_spec,
- vo->opts->drm_opts->drm_mode_spec,
- 0, 0, false);
- if (!p->kms) {
- MP_ERR(vo, "Failed to create KMS.\n");
+ if (!vo_drm_init(vo))
goto err;
- }
-
- if (vo->opts->drm_opts->drm_format == DRM_OPTS_FORMAT_XRGB2101010) {
- p->drm_format = DRM_FORMAT_XRGB2101010;
- p->imgfmt = IMGFMT_XRGB2101010;
- } else {
- p->drm_format = DRM_FORMAT_XRGB8888;;
- p->imgfmt = IMGFMT_XRGB8888;
- }
- p->swapchain_depth = vo->opts->swapchain_depth;
- p->buf_count = p->swapchain_depth + 1;
- if (!fb_setup_buffers(vo)) {
- MP_ERR(vo, "Failed to set up buffers.\n");
- goto err;
- }
+ struct vo_drm_state *drm = vo->drm;
+ p->buf_count = vo->opts->swapchain_depth + 1;
+ p->bufs = talloc_zero_array(p, struct framebuffer *, p->buf_count);
- uint64_t has_dumb = 0;
- if (drmGetCap(p->kms->fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0
- || has_dumb == 0) {
- MP_ERR(vo, "Card \"%d\" does not support dumb buffers.\n",
- p->kms->card_no);
- goto err;
+ p->front_buf = 0;
+ for (int i = 0; i < p->buf_count; i++) {
+ p->bufs[i] = setup_framebuffer(vo);
+ if (!p->bufs[i])
+ goto err;
}
+ drm->fb = p->bufs[0];
- p->screen_w = p->bufs[0].width;
- p->screen_h = p->bufs[0].height;
+ vo->drm->width = vo->drm->fb->width;
+ vo->drm->height = vo->drm->fb->height;
- if (!crtc_setup(vo)) {
- MP_ERR(vo, "Cannot set CRTC: %s\n", mp_strerror(errno));
+ if (!vo_drm_acquire_crtc(vo->drm)) {
+ MP_ERR(vo, "Failed to set CRTC for connector %u: %s\n",
+ vo->drm->connector->connector_id, mp_strerror(errno));
goto err;
}
- if (vo->opts->force_monitor_aspect != 0.0) {
- vo->monitor_par = p->screen_w / (double) p->screen_h /
- vo->opts->force_monitor_aspect;
- } else {
- vo->monitor_par = 1 / vo->opts->monitor_pixel_aspect;
- }
- mp_verbose(vo->log, "Monitor pixel aspect: %g\n", vo->monitor_par);
-
- p->vsync_info.vsync_duration = 0;
- p->vsync_info.skipped_vsyncs = -1;
- p->vsync_info.last_queue_display_time = -1;
-
+ vo_drm_set_monitor_par(vo);
+ p->sws = mp_sws_alloc(vo);
+ p->sws->log = vo->log;
+ mp_sws_enable_cmdline_opts(p->sws, vo->global);
return 0;
err:
@@ -633,43 +421,24 @@ err:
static int query_format(struct vo *vo, int format)
{
- return sws_isSupportedInput(imgfmt2pixfmt(format));
+ struct priv *p = vo->priv;
+ return mp_sws_supports_formats(p->sws, p->imgfmt, format) ? 1 : 0;
}
static int control(struct vo *vo, uint32_t request, void *arg)
{
- struct priv *p = vo->priv;
switch (request) {
- case VOCTRL_SCREENSHOT_WIN:
- *(struct mp_image**)arg = mp_image_new_copy(p->cur_frame);
- return VO_TRUE;
case VOCTRL_SET_PANSCAN:
if (vo->config_ok)
reconfig(vo, vo->params);
return VO_TRUE;
- 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_PAUSE:
- 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;
-}
-#define OPT_BASE_STRUCT struct priv
+ int events = 0;
+ int ret = vo_drm_control(vo, &events, request, arg);
+ vo_event(vo, events);
+ return ret;
+}
const struct vo_driver video_out_drm = {
.name = "drm",
@@ -682,7 +451,7 @@ const struct vo_driver video_out_drm = {
.flip_page = flip_page,
.get_vsync = get_vsync,
.uninit = uninit,
- .wait_events = wait_events,
- .wakeup = wakeup,
+ .wait_events = vo_drm_wait_events,
+ .wakeup = vo_drm_wakeup,
.priv_size = sizeof(struct priv),
};