summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Kindestam <antonki@kth.se>2018-02-19 19:23:44 +0100
committerAnton Kindestam <antonki@kth.se>2019-09-22 15:59:24 +0200
commite2f96535f5f7ca390e334074f64f163db663b822 (patch)
tree81374d41f5c67a428a9907d58d86f74d6465ef30
parent2d1d815cc79d50607ff1cb0432232f23e50c075f (diff)
downloadmpv-e2f96535f5f7ca390e334074f64f163db663b822.tar.bz2
mpv-e2f96535f5f7ca390e334074f64f163db663b822.tar.xz
vo_drm: 30bpp support
-rw-r--r--DOCS/man/vo.rst9
-rw-r--r--RELEASE_NOTES1
-rw-r--r--video/out/vo_drm.c61
3 files changed, 58 insertions, 13 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index ecdea1b94f..f5fd08ca0d 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -548,11 +548,10 @@ Available video output drivers are:
xrgb2101010 is a packed 30 bits per pixel/10 bits per channel packed RGB
format with 2 bits of padding.
- Unless you have an Intel graphics card, a recent kernel and a recent
- version of mesa (>=18) xrgb2101010 is unlikely to work for you.
-
- This currently only has an effect when used together with the ``drm``
- backend for the ``gpu`` VO. The ``drm`` VO always uses xrgb8888.
+ There are cases when xrgb2101010 will work with the ``drm`` VO, but not
+ with the ``drm`` backend for the ``gpu`` VO. This is because with the
+ ``gpu`` VO, in addition to requiring support in your DRM driver,
+ requires support for xrgb2101010 in your EGL driver
``--drm-draw-surface-size=<[WxH]>``
Sets the size of the surface used on the draw plane. The surface will
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 1947c9de0d..c68a639c4f 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -11,6 +11,7 @@ Added
~~~~~
- vo_gpu: Vulkan API implementation based on libplacebo.
+- vo_drm: Add 30bpp support.
Changed
~~~~~~~
diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c
index 281235e911..7d04b0783a 100644
--- a/video/out/vo_drm.c
+++ b/video/out/vo_drm.c
@@ -35,7 +35,13 @@
#include "video/sws_utils.h"
#include "vo.h"
-#define IMGFMT IMGFMT_BGR0
+#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 BYTES_PER_PIXEL 4
#define BITS_PER_PIXEL 32
#define USE_MASTER 0
@@ -70,6 +76,9 @@ struct priv {
bool active;
bool pflip_happening;
+ uint32_t depth;
+ enum mp_imgfmt imgfmt;
+
int32_t screen_w;
int32_t screen_h;
struct mp_image *last_input;
@@ -99,6 +108,8 @@ static void fb_destroy(int fd, struct framebuffer *buf)
static bool fb_setup_single(struct vo *vo, int fd, struct framebuffer *buf)
{
+ struct priv *p = vo->priv;
+
buf->handle = 0;
// create dumb buffer
@@ -116,7 +127,7 @@ static bool fb_setup_single(struct vo *vo, int fd, struct framebuffer *buf)
buf->handle = creq.handle;
// create framebuffer object for the dumb-buffer
- if (drmModeAddFB(fd, buf->width, buf->height, 24, creq.bpp, buf->stride,
+ if (drmModeAddFB(fd, buf->width, buf->height, p->depth, creq.bpp, buf->stride,
buf->handle, &buf->fb)) {
MP_ERR(vo, "Cannot create framebuffer: %s\n", mp_strerror(errno));
goto err;
@@ -280,7 +291,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
mp_sws_set_from_cmdline(p->sws, vo->global);
p->sws->src = *params;
p->sws->dst = (struct mp_image_params) {
- .imgfmt = IMGFMT,
+ .imgfmt = p->imgfmt,
.w = w,
.h = h,
.p_w = 1,
@@ -288,7 +299,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
};
talloc_free(p->cur_frame);
- p->cur_frame = mp_image_alloc(IMGFMT, p->screen_w, p->screen_h);
+ p->cur_frame = mp_image_alloc(p->imgfmt, p->screen_w, p->screen_h);
mp_image_params_guess_csp(&p->sws->dst);
mp_image_set_params(p->cur_frame, &p->sws->dst);
p->cur_frame[0].w = p->screen_w;
@@ -337,10 +348,36 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
}
struct framebuffer *front_buf = &p->bufs[p->front_buf];
- 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]);
+
+ if (p->depth == 30) {
+ // 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 {
+ 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]);
+ }
}
if (mpi != p->last_input) {
@@ -426,6 +463,14 @@ static int preinit(struct vo *vo)
goto err;
}
+ if (vo->opts->drm_opts->drm_format == DRM_OPTS_FORMAT_XRGB2101010) {
+ p->depth = 30;
+ p->imgfmt = IMGFMT_XRGB2101010;
+ } else {
+ p->depth = 24;
+ p->imgfmt = IMGFMT_XRGB8888;
+ }
+
if (!fb_setup_double_buffering(vo)) {
MP_ERR(vo, "Failed to set up double buffering.\n");
goto err;