diff options
author | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2018-06-07 16:25:22 +0200 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2019-02-13 13:01:56 +0100 |
commit | b0033d9310c13eee8fd8268ec0ea16af91c92e6e (patch) | |
tree | 4e93d47c0f132a181f28ff7035a78efd425aafc6 /lib/igt_color_encoding.c | |
parent | 368237db1149033d8274248489ffec671ea1f7d8 (diff) |
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 <maarten.lankhorst@linux.intel.com>
Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com> #v1
Diffstat (limited to 'lib/igt_color_encoding.c')
-rw-r--r-- | lib/igt_color_encoding.c | 91 |
1 files changed, 73 insertions, 18 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); } |