vo_drm: 30bpp support

This commit is contained in:
Anton Kindestam 2018-02-19 19:23:44 +01:00
parent 2d1d815cc7
commit e2f96535f5
3 changed files with 58 additions and 13 deletions

View File

@ -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

View File

@ -11,6 +11,7 @@ Added
~~~~~
- vo_gpu: Vulkan API implementation based on libplacebo.
- vo_drm: Add 30bpp support.
Changed
~~~~~~~

View File

@ -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;