From b0033d9310c13eee8fd8268ec0ea16af91c92e6e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 7 Jun 2018 16:25:22 +0200 Subject: lib/color_encoding: Prepare support for HDR modes, v2. We're starting to add support for 10, 12 and 16-bits formats that all have different values for the Y offset and range. Some 10 bits formats go from [0...1023], others go to [0...1023] shifted left by 6. To accomodate all formats add a struct definition for all various formats, this can be extended further when we add new formats. Changes since v1: - Rebase on top of added yuv changes. - Add commit description (swatish) - Add missing newline. (swatish) Signed-off-by: Maarten Lankhorst Reviewed-by: Juha-Pekka Heikkila #v1 --- lib/igt_color_encoding.c | 91 ++++++++++++++++++++++++++++++++++++++---------- lib/igt_color_encoding.h | 9 +++-- lib/igt_fb.c | 10 ++++-- 3 files changed, 87 insertions(+), 23 deletions(-) diff --git a/lib/igt_color_encoding.c b/lib/igt_color_encoding.c index 03e16e0c..84dc5938 100644 --- a/lib/igt_color_encoding.c +++ b/lib/igt_color_encoding.c @@ -24,6 +24,8 @@ #include "igt_color_encoding.h" #include "igt_matrix.h" #include "igt_core.h" +#include "igt_fb.h" +#include "drmtest.h" struct color_encoding { float kr, kb; @@ -85,60 +87,113 @@ static struct igt_mat4 ycbcr_to_rgb_matrix(const struct color_encoding *e) return ret; } -static struct igt_mat4 ycbcr_input_convert_matrix(enum igt_color_range color_range) +static struct igt_mat4 ycbcr_input_convert_matrix(enum igt_color_range color_range, float scale, + float ofs_y, float max_y, + float ofs_cbcr, float mid_cbcr, float max_cbcr, + float max_val) { struct igt_mat4 t, s; if (color_range == IGT_COLOR_YCBCR_FULL_RANGE) { - t = igt_matrix_translate(0.0f, -128.0f, -128.0f); - s = igt_matrix_scale(1.0f, 2.0f, 2.0f); + t = igt_matrix_translate(0.f, -mid_cbcr, -mid_cbcr); + s = igt_matrix_scale(scale, 2.0f * scale, 2.0f * scale); } else { - t = igt_matrix_translate(-16.0f, -128.0f, -128.0f); - s = igt_matrix_scale(255.0f / (235.0f - 16.0f), - 255.0f / (240.0f - 128.0f), - 255.0f / (240.0f - 128.0f)); + t = igt_matrix_translate(-ofs_y, -mid_cbcr, -mid_cbcr); + s = igt_matrix_scale(scale * max_val / (max_y - ofs_y), + scale * max_val / (max_cbcr - mid_cbcr), + scale * max_val / (max_cbcr - mid_cbcr)); } return igt_matrix_multiply(&s, &t); } -static struct igt_mat4 ycbcr_output_convert_matrix(enum igt_color_range color_range) +static struct igt_mat4 ycbcr_output_convert_matrix(enum igt_color_range color_range, float scale, + float ofs_y, float max_y, + float ofs_cbcr, float mid_cbcr, float max_cbcr, + float max_val) { struct igt_mat4 s, t; if (color_range == IGT_COLOR_YCBCR_FULL_RANGE) { - s = igt_matrix_scale(1.0f, 0.5f, 0.5f); - t = igt_matrix_translate(0.0f, 128.0f, 128.0f); + s = igt_matrix_scale(scale, 0.5f * scale, 0.5f * scale); + t = igt_matrix_translate(0.f, mid_cbcr, mid_cbcr); } else { - s = igt_matrix_scale((235.0f - 16.0f) / 255.0f, - (240.0f - 128.0f) / 255.0f, - (240.0f - 128.0f) / 255.0f); - t = igt_matrix_translate(16.0f, 128.0f, 128.0f); + s = igt_matrix_scale(scale * (max_y - ofs_y) / max_val, + scale * (max_cbcr - mid_cbcr) / max_val, + scale * (max_cbcr - mid_cbcr) / max_val); + t = igt_matrix_translate(ofs_y, mid_cbcr, mid_cbcr); } return igt_matrix_multiply(&t, &s); } -struct igt_mat4 igt_ycbcr_to_rgb_matrix(enum igt_color_encoding color_encoding, +static const struct color_encoding_format { + uint32_t fourcc; + + float max_val; + + float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr; +} formats[] = { + { DRM_FORMAT_XRGB8888, 255.f, }, + { DRM_FORMAT_NV12, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_NV16, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_NV21, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_NV61, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_YUV420, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_YUV422, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_YVU420, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_YVU422, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_YUYV, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_YVYU, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_UYVY, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, + { DRM_FORMAT_VYUY, 255.f, 16.f, 235.f, 16.f, 128.f, 240.f }, +}; + +static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (fourcc == formats[i].fourcc) + return &formats[i]; + + igt_assert_f(0, "Could not look up fourcc %.4s\n", (char *)&fourcc); +} + +struct igt_mat4 igt_ycbcr_to_rgb_matrix(uint32_t from_fourcc, + uint32_t to_fourcc, + enum igt_color_encoding color_encoding, enum igt_color_range color_range) { const struct color_encoding *e = &color_encodings[color_encoding]; struct igt_mat4 r, c; + const struct color_encoding_format *fycbcr = lookup_fourcc(from_fourcc); + const struct color_encoding_format *frgb = lookup_fourcc(to_fourcc); + float scale = frgb->max_val / fycbcr->max_val; - r = ycbcr_input_convert_matrix(color_range); + igt_assert(fycbcr->ofs_y && !frgb->ofs_y); + + r = ycbcr_input_convert_matrix(color_range, scale, fycbcr->ofs_y, fycbcr->max_y, fycbcr->ofs_cbcr, fycbcr->mid_cbcr, fycbcr->max_cbcr, fycbcr->max_val); c = ycbcr_to_rgb_matrix(e); return igt_matrix_multiply(&c, &r); } -struct igt_mat4 igt_rgb_to_ycbcr_matrix(enum igt_color_encoding color_encoding, +struct igt_mat4 igt_rgb_to_ycbcr_matrix(uint32_t from_fourcc, + uint32_t to_fourcc, + enum igt_color_encoding color_encoding, enum igt_color_range color_range) { const struct color_encoding *e = &color_encodings[color_encoding]; + const struct color_encoding_format *frgb = lookup_fourcc(from_fourcc); + const struct color_encoding_format *fycbcr = lookup_fourcc(to_fourcc); struct igt_mat4 c, r; + float scale = fycbcr->max_val / frgb->max_val; + + igt_assert(fycbcr->ofs_y && !frgb->ofs_y); c = rgb_to_ycbcr_matrix(e); - r = ycbcr_output_convert_matrix(color_range); + r = ycbcr_output_convert_matrix(color_range, scale, fycbcr->ofs_y, fycbcr->max_y, fycbcr->ofs_cbcr, fycbcr->mid_cbcr, fycbcr->max_cbcr, fycbcr->max_val); return igt_matrix_multiply(&r, &c); } diff --git a/lib/igt_color_encoding.h b/lib/igt_color_encoding.h index 3884e493..db45b16d 100644 --- a/lib/igt_color_encoding.h +++ b/lib/igt_color_encoding.h @@ -25,6 +25,7 @@ #define __IGT_COLOR_ENCODING_H__ #include +#include #include "igt_matrix.h" @@ -44,9 +45,13 @@ enum igt_color_range { const char *igt_color_encoding_to_str(enum igt_color_encoding encoding); const char *igt_color_range_to_str(enum igt_color_range range); -struct igt_mat4 igt_ycbcr_to_rgb_matrix(enum igt_color_encoding color_encoding, +struct igt_mat4 igt_ycbcr_to_rgb_matrix(uint32_t ycbcr_fourcc, + uint32_t rgb_fourcc, + enum igt_color_encoding color_encoding, enum igt_color_range color_range); -struct igt_mat4 igt_rgb_to_ycbcr_matrix(enum igt_color_encoding color_encoding, +struct igt_mat4 igt_rgb_to_ycbcr_matrix(uint32_t rgb_fourcc, + uint32_t ycbcr_fourcc, + enum igt_color_encoding color_encoding, enum igt_color_range color_range); #endif /* __IGT_COLOR_ENCODING_H__ */ diff --git a/lib/igt_fb.c b/lib/igt_fb.c index cad8bfea..3a4827c3 100644 --- a/lib/igt_fb.c +++ b/lib/igt_fb.c @@ -1564,7 +1564,7 @@ static void *igt_fb_create_cairo_shadow_buffer(int fd, DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE); - shadow->strides[0] = ALIGN(width * 4, 16); + shadow->strides[0] = ALIGN(width * shadow->plane_bpp[0], 16); shadow->size = ALIGN(shadow->strides[0] * height, sysconf(_SC_PAGESIZE)); ptr = mmap(NULL, shadow->size, PROT_READ | PROT_WRITE, @@ -1777,7 +1777,9 @@ static void convert_yuv_to_rgb24(struct fb_convert *cvt) uint8_t *y, *u, *v; uint8_t *rgb24 = cvt->dst.ptr; unsigned int rgb24_stride = cvt->dst.fb->strides[0]; - struct igt_mat4 m = igt_ycbcr_to_rgb_matrix(cvt->src.fb->color_encoding, + struct igt_mat4 m = igt_ycbcr_to_rgb_matrix(cvt->src.fb->drm_format, + cvt->dst.fb->drm_format, + cvt->src.fb->color_encoding, cvt->src.fb->color_range); uint8_t *buf; struct yuv_parameters params = { }; @@ -1838,7 +1840,9 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt) const uint8_t *rgb24 = cvt->src.ptr; uint8_t bpp = 4; unsigned rgb24_stride = cvt->src.fb->strides[0]; - struct igt_mat4 m = igt_rgb_to_ycbcr_matrix(cvt->dst.fb->color_encoding, + struct igt_mat4 m = igt_rgb_to_ycbcr_matrix(cvt->src.fb->drm_format, + cvt->dst.fb->drm_format, + cvt->dst.fb->color_encoding, cvt->dst.fb->color_range); struct yuv_parameters params = { }; -- cgit v1.2.3