Commit b0033d93 authored by Maarten Lankhorst's avatar Maarten Lankhorst

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: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com> #v1
parent 368237db
......@@ -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);
}
......
......@@ -25,6 +25,7 @@
#define __IGT_COLOR_ENCODING_H__
#include <stdbool.h>
#include <stdint.h>
#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__ */
......@@ -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 = { };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment