From f05c8c2739dce89185349703062784a7745cab14 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Mon, 17 Dec 2018 16:30:28 +0200 Subject: lib/igt_fb: Added XYUV8888 format support for testing XYUV8888 format support has been added to DRM, modified IGT to reflect those changes. v2: Fixed merge conflict, started to use new yuv<=>rgb conversion functions. v3: Fixed kms_available_modes_crc test to support new XYUV format. Fixed a problem, where test complains that two outputs might use same pipe at the same time. v4: Fixed convertion procedure in igt_fb to support XYUV properly. v5: Fixed a coding typo. v6: Set depth equal to -1 for XYUV format in order to prevent it to be used by igt_bpp_depth_to_drm_format, as we do not want YUV formats to be used in that case. v7: Fix "black" color initialization for create_bo_for_fb with proper value. Changed naming "planar_stride" to "xyuv_stride". v8: Change naming from DRM_FORMAT_XYUV to DRM_FORMAT_XYUV8888 v9: Fixed compilation errors by rebasing to recent master. v10: Adding reference to correspondent kernel commit with the new format in include/drm-uapi v11: Removed unnecessary sizeof's in rgb <=> yuv444 convert functions. v12: Rebased against master branch, fixed rebase conflict caused by new fb_convert functions. Removed drm kernel commit reference as it is still not merged, so doesn't make sense to use it. v13: Resolved one more rebase conflict. Signed-off-by: Stanislav Lisovskiy Signed-off-by: Maarten Lankhorst --- include/drm-uapi/drm_fourcc.h | 2 +- lib/igt_fb.c | 89 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/include/drm-uapi/drm_fourcc.h b/include/drm-uapi/drm_fourcc.h index 0b44260a..4ddf754b 100644 --- a/include/drm-uapi/drm_fourcc.h +++ b/include/drm-uapi/drm_fourcc.h @@ -151,7 +151,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_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ /* * packed YCbCr420 2x2 tiled formats diff --git a/lib/igt_fb.c b/lib/igt_fb.c index 2462d6ba..57264844 100644 --- a/lib/igt_fb.c +++ b/lib/igt_fb.c @@ -102,6 +102,10 @@ static const struct format_desc_struct { .pixman_id = PIXMAN_r8g8b8, .num_planes = 1, .plane_bpp = { 24, }, }, + { .name = "XYUV8888", .depth = -1, .drm_id = DRM_FORMAT_XYUV8888, + .cairo_id = CAIRO_FORMAT_RGB24, + .num_planes = 1, .plane_bpp = { 32, }, + }, { .name = "XRGB8888", .depth = 24, .drm_id = DRM_FORMAT_XRGB8888, .cairo_id = CAIRO_FORMAT_RGB24, .pixman_id = PIXMAN_x8r8g8b8, @@ -496,6 +500,10 @@ static int create_bo_for_fb(struct igt_fb *fb) 0x80, fb->strides[1] * fb->plane_height[1]); break; + case DRM_FORMAT_XYUV8888: + wmemset(ptr + fb->offsets[0], full_range ? 0x00008080 : 0x00108080, + fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t)); + break; case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: wmemset(ptr + fb->offsets[0], @@ -1649,6 +1657,79 @@ static void convert_nv12_to_rgb24(struct fb_convert *cvt) convert_src_put(cvt, buf); } +static void convert_yuv444_to_rgb24(struct fb_convert *cvt) +{ + int i, j; + uint8_t *yuv24; + uint8_t *rgb24 = cvt->dst.ptr; + unsigned rgb24_stride = cvt->dst.fb->strides[0], xyuv_stride = cvt->src.fb->strides[0]; + uint8_t *buf = malloc(cvt->src.fb->size); + struct igt_mat4 m = igt_ycbcr_to_rgb_matrix(cvt->src.fb->color_encoding, + cvt->src.fb->color_range); + + /* + * 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, cvt->src.ptr + cvt->src.fb->offsets[0], cvt->src.fb->size); + yuv24 = buf; + + for (i = 0; i < cvt->dst.fb->height; i++) { + for (j = 0; j < cvt->dst.fb->width; j++) { + float y, u, v; + struct igt_vec4 yuv; + struct igt_vec4 rgb; + + v = yuv24[i * xyuv_stride + j * 4]; + u = yuv24[i * xyuv_stride + j * 4 + 1]; + y = yuv24[i * xyuv_stride + j * 4 + 2]; + yuv.d[0] = y; + yuv.d[1] = u; + yuv.d[2] = v; + yuv.d[3] = 1.0f; + + rgb = igt_matrix_transform(&m, &yuv); + + write_rgb(&rgb24[i * rgb24_stride + j * 4], &rgb); + } + } + + free(buf); +} + + +static void convert_rgb24_to_yuv444(struct fb_convert *cvt) +{ + int i, j; + uint8_t *rgb24; + uint8_t *yuv444 = cvt->dst.ptr + cvt->dst.fb->offsets[0]; + unsigned int rgb24_stride = cvt->src.fb->strides[0], xyuv_stride = cvt->dst.fb->strides[0]; + struct igt_mat4 m = igt_rgb_to_ycbcr_matrix(cvt->dst.fb->color_encoding, + cvt->dst.fb->color_range); + + rgb24 = cvt->src.ptr; + + igt_assert_f(cvt->dst.fb->drm_format == DRM_FORMAT_XYUV8888, + "Conversion not implemented for !XYUV packed formats\n"); + + for (i = 0; i < cvt->dst.fb->height; i++) { + for (j = 0; j < cvt->dst.fb->width; j++) { + struct igt_vec4 rgb; + struct igt_vec4 yuv; + float y, u, v; + + read_rgb(&rgb, &rgb24[i * rgb24_stride + j * 4]); + + yuv = igt_matrix_transform(&m, &rgb); + + yuv444[i * xyuv_stride + j * 4] = yuv.d[2]; + yuv444[i * xyuv_stride + j * 4 + 1] = yuv.d[1]; + yuv444[i * xyuv_stride + j * 4 + 2] = yuv.d[0]; + } + } +} + static void convert_rgb24_to_nv12(struct fb_convert *cvt) { int i, j; @@ -1934,6 +2015,9 @@ static void fb_convert(struct fb_convert *cvt) return; } else if (cvt->dst.fb->drm_format == DRM_FORMAT_XRGB8888) { switch (cvt->src.fb->drm_format) { + case DRM_FORMAT_XYUV8888: + convert_yuv444_to_rgb24(cvt); + return; case DRM_FORMAT_NV12: convert_nv12_to_rgb24(cvt); return; @@ -1946,6 +2030,9 @@ static void fb_convert(struct fb_convert *cvt) } } else if (cvt->src.fb->drm_format == DRM_FORMAT_XRGB8888) { switch (cvt->dst.fb->drm_format) { + case DRM_FORMAT_XYUV8888: + convert_rgb24_to_yuv444(cvt); + return; case DRM_FORMAT_NV12: convert_rgb24_to_nv12(cvt); return; @@ -2037,6 +2124,7 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb) blit, destroy_cairo_surface__convert); } + /** * igt_fb_map_buffer: * @fd: open drm file descriptor @@ -2302,6 +2390,7 @@ bool igt_format_is_yuv(uint32_t drm_format) case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: case DRM_FORMAT_VYUY: + case DRM_FORMAT_XYUV8888: return true; default: return false; -- cgit v1.2.3