[igt-dev] [PATCH i-g-t] lib/igt_fb: Added XYUV format support for testing
Ville Syrjälä
ville.syrjala at linux.intel.com
Tue Aug 28 12:57:41 UTC 2018
On Tue, Aug 28, 2018 at 01:45:22PM +0300, Stanislav Lisovskiy wrote:
> XYUV format support has been added to DRM, modified
> IGT to reflect those changes.
> ---
> include/drm-uapi/drm_fourcc.h | 1 +
> lib/igt_fb.c | 160 +++++++++++++++++++++++++++++++++-
> 2 files changed, 160 insertions(+), 1 deletion(-)
>
> diff --git a/include/drm-uapi/drm_fourcc.h b/include/drm-uapi/drm_fourcc.h
> index e04613d3..0bf66de2 100644
> --- a/include/drm-uapi/drm_fourcc.h
> +++ b/include/drm-uapi/drm_fourcc.h
> @@ -112,6 +112,7 @@ extern "C" {
> #define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
>
> #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
> +#define DRM_FORMAT_XYUV fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
>
> /*
> * 2 plane RGB + A
> diff --git a/lib/igt_fb.c b/lib/igt_fb.c
> index 7404ba7c..27f9d657 100644
> --- a/lib/igt_fb.c
> +++ b/lib/igt_fb.c
> @@ -68,6 +68,8 @@ static struct format_desc_struct {
> } format_desc[] = {
> DF(RGB565, RGB16_565, 16, 16),
> //DF(RGB888, INVALID, 24, 24),
> + DF(XYUV, RGB24, 32, 24, 1, {32}),
> + DF(XRGB8888, RGB24, 32, 24),
> DF(XRGB8888, RGB24, 32, 24),
> DF(XRGB2101010, RGB30, 32, 30),
> DF(ARGB8888, ARGB32, 32, 32),
> @@ -1399,6 +1401,94 @@ static void convert_nv12_to_rgb24(struct igt_fb *fb, struct fb_convert_blit_uplo
> free(buf);
> }
>
> +#define MAKE_YUV_601_Y(r, g, b) \
> + ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) / 256) + 16)
> +#define MAKE_YUV_601_U(r, g, b) \
> + (((-38 * (r) - 74 * (g) + 112 * (b) + 128) / 256) + 128)
> +#define MAKE_YUV_601_V(r, g, b) \
> + (((112 * (r) - 94 * (g) - 18 * (b) + 128) / 256) + 128)
Reuse the yuv<->rgb stuff we already have.
> +
> +#define MAKE_RGB_24_R(y, u, v) \
> + (y + 0 * u + 1.13983 * v)
> +
> +#define MAKE_RGB_24_G(y, u, v) \
> + (y + -0.39465 * u + -0.58060 * v)
> +
> +#define MAKE_RGB_24_B(y, u, v) \
> + (y + -0.03211 * u + 0 * v)
> +
> +static void convert_yuv444_to_rgb24(struct igt_fb *fb, struct fb_convert_blit_upload *blit)
> +{
> + int i, j;
> + uint8_t *yuv;
> + uint8_t *rgb24 = blit->rgb24.map;
> + unsigned rgb24_stride = blit->rgb24.stride, planar_stride = blit->linear.stride;
> + uint8_t *buf = malloc(blit->linear.size);
> +
> + /*
> + * Reading from the BO is awfully slow because of lack of read caching,
> + * it's faster to copy the whole BO to a temporary buffer and convert
> + * from there.
> + */
> + igt_memcpy_from_wc(buf, blit->linear.map, blit->linear.size);
> + yuv = &buf[blit->linear.offsets[0]];
> +
> + for (i = 0; i < fb->plane_height[0]; i++) {
> + for (j = 0; j < fb->plane_width[0]; j++) {
> + float r, g, b, y, u, v;
> + v = yuv[i * planar_stride + j*sizeof(uint32_t)];
> + u = yuv[i * planar_stride + j*sizeof(uint32_t) + 1];
> + y = yuv[i * planar_stride + j*sizeof(uint32_t) + 2];
> + r = MAKE_RGB_24_R(y,u,v);
> + g = MAKE_RGB_24_G(y,u,v);
> + b = MAKE_RGB_24_B(y,u,v);
> + rgb24[i * rgb24_stride + j*sizeof(uint32_t)] = b;
> + rgb24[i * rgb24_stride + j*sizeof(uint32_t) + 1] = g;
> + rgb24[i * rgb24_stride + j*sizeof(uint32_t) + 2] = r;
> + }
> + }
> +
> + free(buf);
> +}
> +
> +
> +static void convert_rgb24_to_yuv444(struct igt_fb *fb, struct fb_convert_blit_upload *blit)
> +{
> + int i, j;
> + uint8_t *rgb;
> + uint8_t *yuv444 = blit->linear.map;
> + unsigned rgb24_stride = blit->rgb24.stride, planar_stride = blit->linear.stride;
> + uint8_t *buf = malloc(blit->linear.size);
> +
> + /*
> + * Reading from the BO is awfully slow because of lack of read caching,
> + * it's faster to copy the whole BO to a temporary buffer and convert
> + * from there.
> + */
> + igt_memcpy_from_wc(buf, blit->rgb24.map, blit->linear.size);
> + rgb = &buf[blit->linear.offsets[0]];
> +
> + for (i = 0; i < fb->plane_height[0]; i++) {
> + for (j = 0; j < fb->plane_width[0]; j++) {
> + float r, g, b, y, u, v;
> + b = rgb[i * rgb24_stride + j*sizeof(uint32_t)];
> + g = rgb[i * rgb24_stride + j*sizeof(uint32_t) + 1];
> + r = rgb[i * rgb24_stride + j*sizeof(uint32_t) + 2];
> + y = MAKE_YUV_601_Y(r,g,b);
> + u = MAKE_YUV_601_U(r,g,b);
> + v = MAKE_YUV_601_V(r,g,b);
> + yuv444[i * planar_stride + j*sizeof(uint32_t)] = v;
> + yuv444[i * planar_stride + j*sizeof(uint32_t) + 1] = u;
> + yuv444[i * planar_stride + j*sizeof(uint32_t) + 2] = y;
> + }
> + }
> +
> + free(buf);
> +}
> +
> +
> +
> +
> static void convert_rgb24_to_nv12(struct igt_fb *fb, struct fb_convert_blit_upload *blit)
> {
> int i, j;
> @@ -1534,6 +1624,72 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb)
> blit, destroy_cairo_surface__convert);
> }
>
> +
> +static void destroy_cairo_surface__convert_yuv(void *arg)
> +{
> + struct fb_convert_blit_upload *blit = arg;
> + struct igt_fb *fb = blit->fb;
> +
> + /* Convert back to planar! */
> + igt_assert_f(fb->drm_format == DRM_FORMAT_XYUV,
> + "Conversion not implemented for !XYUV planar formats\n");
> +
> + convert_rgb24_to_yuv444(fb, blit);
> +
> + munmap(blit->rgb24.map, blit->rgb24.size);
> +
> + if (blit->linear.handle)
> + free_linear_mapping(blit->fd, blit->fb, &blit->linear);
> + else
> + gem_munmap(blit->linear.map, fb->size);
> +
> + free(blit);
> +
> + fb->cairo_surface = NULL;
> +}
> +
> +
> +static void create_cairo_surface__convert_yuv(int fd, struct igt_fb *fb)
No need to duplicate all this. Just add the xyuv case to the existing
function.
> +{
> + struct fb_convert_blit_upload *blit = malloc(sizeof(*blit));
> + igt_assert(blit);
> +
> + blit->fd = fd;
> + blit->fb = fb;
> + blit->rgb24.stride = ALIGN(fb->width * 4, 16);
> + blit->rgb24.size = ALIGN(blit->rgb24.stride * fb->height, sysconf(_SC_PAGESIZE));
> + blit->rgb24.map = mmap(NULL, blit->rgb24.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> + igt_assert(blit->rgb24.map != MAP_FAILED);
> +
> + if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
> + fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) {
> + setup_linear_mapping(fd, fb, &blit->linear);
> + } else {
> + blit->linear.handle = 0;
> + blit->linear.map = gem_mmap__gtt(fd, fb->gem_handle, fb->size,
> + PROT_READ | PROT_WRITE);
> + igt_assert(blit->linear.map);
> + blit->linear.stride = fb->stride;
> + blit->linear.size = fb->size;
> + memcpy(blit->linear.offsets, fb->offsets, sizeof(fb->offsets));
> + }
> +
> + /* Convert to linear! */
> + igt_assert_f(fb->drm_format == DRM_FORMAT_XYUV,
> + "Conversion not implemented for !XYUV planar formats\n");
> + convert_yuv444_to_rgb24(fb, blit);
> +
> + fb->cairo_surface =
> + cairo_image_surface_create_for_data(blit->rgb24.map,
> + CAIRO_FORMAT_RGB24,
> + fb->width, fb->height,
> + blit->rgb24.stride);
> +
> + cairo_surface_set_user_data(fb->cairo_surface,
> + (cairo_user_data_key_t *)create_cairo_surface__convert_yuv,
> + blit, destroy_cairo_surface__convert_yuv);
> +}
> +
> /**
> * igt_get_cairo_surface:
> * @fd: open drm file descriptor
> @@ -1548,7 +1704,9 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb)
> cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb)
> {
> if (fb->cairo_surface == NULL) {
> - if (fb->num_planes > 1)
> + if (fb->drm_format == DRM_FORMAT_XYUV)
> + create_cairo_surface__convert_yuv(fd, fb);
> + else if (fb->num_planes > 1)
> create_cairo_surface__convert(fd, fb);
> else if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
> fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED)
> --
> 2.17.0
>
> _______________________________________________
> igt-dev mailing list
> igt-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
--
Ville Syrjälä
Intel
More information about the igt-dev
mailing list