Skip to contentSkip to conversation

lib/color_encoding: Prepare support for HDR modes.

PATCH In review Maarten Lankhorst 4 participants 17 messages Feb 7, 2019 – Feb 8, 2019

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/4 lib/color_encoding: Prepare support for HDR modes.

---
 lib/igt_color_encoding.c | 83 +++++++++++++++++++++++++++++++---------
 lib/igt_color_encoding.h |  9 ++++-
 lib/igt_fb.c             | 10 +++--
 3 files changed, 79 insertions(+), 23 deletions(-)
lib/igt_color_encoding.c +65 -18
index 03e16e0c9658..4cbe18e217e3 100644
@@ -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,105 @@ 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_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);
 }
lib/igt_color_encoding.h +7 -2
index 3884e4939f4c..db45b16d3687 100644
@@ -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__ */
lib/igt_fb.c +7 -3
index 5d8c187a9ac9..db3ae06748d1 100644
@@ -1508,7 +1508,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,
@@ -1681,7 +1681,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 = { };
@@ -1742,7 +1744,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 = { };
 
Signature · 6 lines
2.20.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#1 lore raw

PATCH v2 2/4 lib/igt_fb: Add support for P01x formats, v4.

The P01x formats are planar 16 bits per component, with the unused lower bits set to 0. This means they can all be converted the same way. Only the range is slightly different, and this is handled in the color_encoding implementation.

This requires cairo 1.17.2 and pixman 0.36. This works but doesn't give extra precision. For more than 8 bits precision a few more patches are required to pixman, pending review:
https://lists.freedesktop.org/archives/pixman/2019-January/004815.html
https://lists.freedesktop.org/archives/pixman/2019-January/004809.html

Once those are merged, we will require the next pixman release for better precision.

Changes since v1:
- Add fallback color definitions when compiling on cairo version < 1.17.2.
- Skip when FB creation fails on HDR formats, instead of failing. Changes since v2:
- Complain slightly harder when pixman/cairo are out of date.
- Create a fb with alpha when converting to pixman formats with alpha.
- Oops, s/pixman_format_code_t/cairo_format_t/
Changes since v3:
- Rebase on top of upstream YUV changes.

---
 configure.ac                  |  11 +-
 include/drm-uapi/drm_fourcc.h |  10 ++
 lib/igt_color_encoding.c      |   4 +
 lib/igt_fb.c                  | 293 +++++++++++++++++++++++++++++++++-
 lib/igt_fb.h                  |   6 +
 meson.build                   |  10 ++
 6 files changed, 329 insertions(+), 5 deletions(-)
configure.ac +9 -2
index b46f024f875a..a333cf8d6dbb 100644
@@ -136,10 +136,17 @@ fi
 PKG_CHECK_MODULES(XRANDR, xrandr >= 1.3, AC_DEFINE(HAVE_XRANDR, 1, [Have libXrandr]), [have_xrandr=no])
 
 # for testdisplay
-PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])
+PKG_CHECK_MODULES(CAIRO, [cairo >= 1.17.2], [],
+	[AC_MSG_WARN([Cairo too old, HDR formats not available. Upgrade to cairo 1.17.2])
+	PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])]
+)
 PKG_CHECK_MODULES(LIBUDEV, [libudev])
 PKG_CHECK_MODULES(GLIB, [glib-2.0])
-PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+PKG_CHECK_MODULES(PIXMAN, [pixman-1 >= 0.36.0], [], [
+	AC_MSG_WARN([Pixman too old, HDR formats not available. Upgrade to pixman 0.36.0])
+	PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+])
+
 PKG_CHECK_MODULES(GSL, [gsl], [gsl=yes], [gsl=no])
 AM_CONDITIONAL(HAVE_GSL, [test "x$gsl" = xyes])
 
include/drm-uapi/drm_fourcc.h +10 -0
index 41106c835747..fe6b66ef1756 100644
@@ -195,6 +195,16 @@ extern "C" {
 #define DRM_FORMAT_NV24		fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
 #define DRM_FORMAT_NV42		fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
 
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [15:0] Y little endian where Pxxx indicate
+ * component xxx msb Y [xxx:16-xxx]
+ * index 1 = Cr:Cb plane, [31:0] Cr:Cb little endian [xxx:16-xxx:xxx:16-xxx]
+ */
+#define DRM_FORMAT_P010		fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane, 10 bit per channel */
+#define DRM_FORMAT_P012		fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane, 12 bit per channel */
+#define DRM_FORMAT_P016		fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane, 16 bit per channel */
+
 /*
  * 3 plane YCbCr
  * index 0: Y plane, [7:0] Y
lib/igt_color_encoding.c +4 -0
index 4cbe18e217e3..b7a12a1e07f7 100644
@@ -135,11 +135,15 @@ static const struct color_encoding_format {
 	float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr;
 } formats[] = {
 	{ DRM_FORMAT_XRGB8888, 255.f, },
+	{ IGT_FORMAT_FLOAT, 1.f, },
 	{ DRM_FORMAT_NV12, 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 },
+	{ DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 };
 
 static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +290 -3

382 lines not on this page · raw message

lib/igt_fb.h +6 -0
index 9f027deba842..8c683db5e9ec 100644
@@ -38,6 +38,12 @@
 
 #include "igt_color_encoding.h"
 
+/*
+ * Internal format to denote a buffer compatible with pixman's
+ * floating point format. Range [0-1].
+ */
+#define IGT_FORMAT_FLOAT fourcc_code('I', 'G', 'F', 'x')
+
 /**
  * igt_fb_t:
  * @fb_id: KMS ID of the framebuffer
meson.build +10 -0
index b17e67ef7f05..356a5414226b 100644
@@ -336,3 +336,13 @@ message('=============')
 foreach str : build_info
 	message(str)
 endforeach
+
+if cairo.version().version_compare('<1.17.2')
+	if pixman.version().version_compare('<0.36.0')
+		warning('Pixman < 0.36.0 found, cannot test HDR formats')
+	endif
+	warning('Cairo < 1.17.2 found, cannot test HDR formats')
+elif pixman.version().version_compare('<0.36.0')
+	# Cairo 1.17.2 requires 0.36.0 to compile, but somehow it went missing?
+	error('Cairo with floating point support found, but pixman version too old')
+endif
Signature · 6 lines
2.20.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#2 lore raw

Re: [igt-dev] [PATCH v2 2/4] lib/igt_fb: Add support for P01x formats, v4.

Quoted 180 lines · Maarten Lankhorst

The P01x formats are planar 16 bits per component, with the unused lower bits set to 0. This means they can all be converted the same way. Only the range is slightly different, and this is handled in the color_encoding implementation.

This requires cairo 1.17.2 and pixman 0.36. This works but doesn't give extra precision. For more than 8 bits precision a few more patches are required to pixman, pending review:
https://lists.freedesktop.org/archives/pixman/2019-January/004815.html
https://lists.freedesktop.org/archives/pixman/2019-January/004809.html

Once those are merged, we will require the next pixman release for better precision.

Changes since v1:
- Add fallback color definitions when compiling on cairo version < 1.17.2.
- Skip when FB creation fails on HDR formats, instead of failing. Changes since v2:
- Complain slightly harder when pixman/cairo are out of date.
- Create a fb with alpha when converting to pixman formats with alpha.
- Oops, s/pixman_format_code_t/cairo_format_t/
Changes since v3:
- Rebase on top of upstream YUV changes.

---
  configure.ac                  |  11 +-
  include/drm-uapi/drm_fourcc.h |  10 ++
  lib/igt_color_encoding.c      |   4 +
  lib/igt_fb.c                  | 293 +++++++++++++++++++++++++++++++++-
  lib/igt_fb.h                  |   6 +
  meson.build                   |  10 ++
  6 files changed, 329 insertions(+), 5 deletions(-)
configure.ac +9 -2
index b46f024f875a..a333cf8d6dbb 100644
@@ -136,10 +136,17 @@ fi
  PKG_CHECK_MODULES(XRANDR, xrandr >= 1.3, AC_DEFINE(HAVE_XRANDR, 1, [Have libXrandr]), [have_xrandr=no])
 
  # for testdisplay
-PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])
+PKG_CHECK_MODULES(CAIRO, [cairo >= 1.17.2], [],
+	[AC_MSG_WARN([Cairo too old, HDR formats not available. Upgrade to cairo 1.17.2])
+	PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])]
+)
  PKG_CHECK_MODULES(LIBUDEV, [libudev])
  PKG_CHECK_MODULES(GLIB, [glib-2.0])
-PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+PKG_CHECK_MODULES(PIXMAN, [pixman-1 >= 0.36.0], [], [
+	AC_MSG_WARN([Pixman too old, HDR formats not available. Upgrade to pixman 0.36.0])
+	PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+])
+
  PKG_CHECK_MODULES(GSL, [gsl], [gsl=yes], [gsl=no])
  AM_CONDITIONAL(HAVE_GSL, [test "x$gsl" = xyes])
 
include/drm-uapi/drm_fourcc.h +10 -0
index 41106c835747..fe6b66ef1756 100644
@@ -195,6 +195,16 @@ extern "C" {
  #define DRM_FORMAT_NV24		fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
  #define DRM_FORMAT_NV42		fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
 
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [15:0] Y little endian where Pxxx indicate
+ * component xxx msb Y [xxx:16-xxx]
+ * index 1 = Cr:Cb plane, [31:0] Cr:Cb little endian [xxx:16-xxx:xxx:16-xxx]
+ */
+#define DRM_FORMAT_P010		fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane, 10 bit per channel */
+#define DRM_FORMAT_P012		fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane, 12 bit per channel */
+#define DRM_FORMAT_P016		fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane, 16 bit per channel */
+
  /*
   * 3 plane YCbCr
   * index 0: Y plane, [7:0] Y
lib/igt_color_encoding.c +4 -0
index 4cbe18e217e3..b7a12a1e07f7 100644
@@ -135,11 +135,15 @@ static const struct color_encoding_format {
  	float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr;
  } formats[] = {
  	{ DRM_FORMAT_XRGB8888, 255.f, },
+	{ IGT_FORMAT_FLOAT, 1.f, },
  	{ DRM_FORMAT_NV12, 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 },
+	{ DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  };
 
  static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +43 -1
index db3ae06748d1..12763cc85c86 100644
@@ -62,6 +62,20 @@
 
  #define PIXMAN_invalid	0
 
+#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 17, 2)
+/*
+ * We need cairo 1.17.2 to use HDR formats, but the only thing added is a value
+ * to cairo_format_t.
+ *
+ * To prevent going outside the enum, make cairo_format_t an int and define
+ * ourselves.
+ */
+
+#define CAIRO_FORMAT_RGB96F (6)
+#define CAIRO_FORMAT_RGBA128F (7)
+#define cairo_format_t int
+#endif
+
  /* drm fourcc/cairo format maps */
  static const struct format_desc_struct {
  	const char *name;
@@ -170,6 +184,25 @@ static const struct format_desc_struct {
  	  .num_planes = 1, .plane_bpp = { 16, },
  	  .hsub = 2, .vsub = 1,
  	},
+	{ .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 2, .plane_bpp = { 16, 32 },
+	  .vsub = 2, .hsub = 2,
+	},
+	{ .name = "P012", .depth = -1, .drm_id = DRM_FORMAT_P012,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 2, .plane_bpp = { 16, 32 },
+	  .vsub = 2, .hsub = 2,
+	},
+	{ .name = "P016", .depth = -1, .drm_id = DRM_FORMAT_P016,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 2, .plane_bpp = { 16, 32 },
+	  .vsub = 2, .hsub = 2,
+	},
+	{ .name = "IGT-FLOAT", .depth = -1, .drm_id = IGT_FORMAT_FLOAT,
+	  .cairo_id = CAIRO_FORMAT_INVALID,
+	  .num_planes = 1, .plane_bpp = { 128 },
+	},
  };
  #define for_each_format(f)	\
  	for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++)
@@ -520,6 +553,14 @@ static void clear_yuv_buffer(struct igt_fb *fb)
  			full_range ? 0x00800080 : 0x10801080,
  			fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
  		break;
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		wmemset(ptr, full_range ? 0 : 0x10001000,
+			fb->offsets[1] / sizeof(wchar_t));
+		wmemset(ptr + fb->offsets[1], 0x80008000,
+			fb->strides[1] * fb->plane_height[1] / sizeof(wchar_t));
+		break;
  	}
 
  	igt_fb_unmap_buffer(fb, ptr);
@@ -1496,6 +1537,7 @@ struct fb_convert_blit_upload {
  };
 
  static void *igt_fb_create_cairo_shadow_buffer(int fd,
+					       unsigned drm_format,
  					       unsigned int width,
  					       unsigned int height,
  					       struct igt_fb *shadow)
@@ -1505,7 +1547,7 @@ static void *igt_fb_create_cairo_shadow_buffer(int fd,
  	igt_assert(shadow);
 
  	fb_init(shadow, fd, width, height,
-		DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+		drm_format, LOCAL_DRM_FORMAT_MOD_NONE,
  		IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
 
  	shadow->strides[0] = ALIGN(width * shadow->plane_bpp[0], 16);

lib/igt_fb.c static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params) · line 1648

Quoted 8 lines
lib/igt_fb.c +3 -0
@@ -1599,6 +1641,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
 
  	switch (fb->drm_format) {
  	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
  		params->y_inc = 1;
  		params->uv_inc = 2;

Hi Maarten,

I was wondering if above y_inc and uv_inc for Pxxx should be 2x of those for NV12?

I noticed they're used below like "y_tmp += params.y_inc" where y_tmp is uint8_t*.

Other than this all look good to me in this patch. I don't have HW to test with so I cannot go see how it work.

/Juha-Pekka

Quoted 334 lines
lib/igt_fb.c +244 -2
  		break;
@@ -1619,6 +1664,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
 
  	switch (fb->drm_format) {
  	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
  		params->y_stride = fb->strides[0];
  		params->uv_stride = fb->strides[1];
  		break;
@@ -1640,6 +1688,14 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  		params->v_offset = fb->offsets[1] + 1;
  		break;
 
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		params->y_offset = fb->offsets[0];
+		params->u_offset = fb->offsets[1];
+		params->v_offset = fb->offsets[1] + 2;
+		break;
+
  	case DRM_FORMAT_YUYV:
  		params->y_offset = fb->offsets[0];
  		params->u_offset = fb->offsets[0] + 1;
@@ -1821,6 +1877,178 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt)
  	}
  }
 
+static void read_rgbf(struct igt_vec4 *rgb, const float *rgb24)
+{
+	rgb->d[0] = rgb24[0];
+	rgb->d[1] = rgb24[1];
+	rgb->d[2] = rgb24[2];
+	rgb->d[3] = 1.0f;
+}
+
+static void write_rgbf(float *rgb24, const struct igt_vec4 *rgb)
+{
+	rgb24[0] = rgb->d[0];
+	rgb24[1] = rgb->d[1];
+	rgb24[2] = rgb->d[2];
+}
+
+static void convert_yuv16_to_float(struct fb_convert *cvt)
+{
+	const struct format_desc_struct *src_fmt =
+		lookup_drm_format(cvt->src.fb->drm_format);
+	int i, j;
+	uint8_t fpp = 3;
+	uint16_t *y, *u, *v;
+	float *ptr = cvt->dst.ptr;
+	unsigned int float_stride = cvt->dst.fb->strides[0] / sizeof(*ptr);
+	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);
+	uint16_t *buf;
+	struct yuv_parameters params = { };
+
+	igt_assert(cvt->dst.fb->drm_format == IGT_FORMAT_FLOAT &&
+		   igt_format_is_yuv(cvt->src.fb->drm_format));
+
+	buf = convert_src_get(cvt);
+	get_yuv_parameters(cvt->src.fb, &params);
+	igt_assert(!(params.y_offset % sizeof(*buf)) &&
+		   !(params.u_offset % sizeof(*buf)) &&
+		   !(params.v_offset % sizeof(*buf)));
+
+	y = buf + params.y_offset / sizeof(*buf);
+	u = buf + params.u_offset / sizeof(*buf);
+	v = buf + params.v_offset / sizeof(*buf);
+
+	for (i = 0; i < cvt->dst.fb->height; i++) {
+		const uint16_t *y_tmp = y;
+		const uint16_t *u_tmp = u;
+		const uint16_t *v_tmp = v;
+		float *rgb_tmp = ptr;
+
+		for (j = 0; j < cvt->dst.fb->width; j++) {
+			struct igt_vec4 rgb, yuv;
+
+			yuv.d[0] = *y_tmp;
+			yuv.d[1] = *u_tmp;
+			yuv.d[2] = *v_tmp;
+			yuv.d[3] = 1.0f;
+
+			rgb = igt_matrix_transform(&m, &yuv);
+			write_rgbf(rgb_tmp, &rgb);
+
+			rgb_tmp += fpp;
+			y_tmp += params.y_inc;
+
+			if ((src_fmt->hsub == 1) || (j % src_fmt->hsub)) {
+				u_tmp += params.uv_inc;
+				v_tmp += params.uv_inc;
+			}
+		}
+
+		ptr += float_stride;
+		y += params.y_stride / sizeof(*y);
+
+		if ((src_fmt->vsub == 1) || (i % src_fmt->vsub)) {
+			u += params.uv_stride / sizeof(*u);
+			v += params.uv_stride / sizeof(*v);
+		}
+	}
+
+	convert_src_put(cvt, buf);
+}
+
+static void convert_float_to_yuv16(struct fb_convert *cvt)
+{
+	const struct format_desc_struct *dst_fmt =
+		lookup_drm_format(cvt->dst.fb->drm_format);
+	int i, j;
+	uint16_t *y, *u, *v;
+	const float *ptr = cvt->src.ptr;
+	uint8_t fpp = 3;
+	unsigned float_stride = cvt->src.fb->strides[0] / sizeof(*ptr);
+	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 = { };
+
+	igt_assert(cvt->src.fb->drm_format == IGT_FORMAT_FLOAT &&
+		   igt_format_is_yuv(cvt->dst.fb->drm_format));
+
+	get_yuv_parameters(cvt->dst.fb, &params);
+	igt_assert(!(params.y_offset % sizeof(*y)) &&
+		   !(params.u_offset % sizeof(*u)) &&
+		   !(params.v_offset % sizeof(*v)));
+
+	y = cvt->dst.ptr + params.y_offset;
+	u = cvt->dst.ptr + params.u_offset;
+	v = cvt->dst.ptr + params.v_offset;
+
+	for (i = 0; i < cvt->dst.fb->height; i++) {
+		const float *rgb_tmp = ptr;
+		uint16_t *y_tmp = y;
+		uint16_t *u_tmp = u;
+		uint16_t *v_tmp = v;
+
+		for (j = 0; j < cvt->dst.fb->width; j++) {
+			const float *pair_float = rgb_tmp;
+			struct igt_vec4 pair_rgb, rgb;
+			struct igt_vec4 pair_yuv, yuv;
+
+			read_rgbf(&rgb, rgb_tmp);
+			yuv = igt_matrix_transform(&m, &rgb);
+
+			rgb_tmp += fpp;
+
+			*y_tmp = yuv.d[0];
+			y_tmp += params.y_inc;
+
+			if ((i % dst_fmt->vsub) || (j % dst_fmt->hsub))
+				continue;
+
+			/*
+			 * We assume the MPEG2 chroma siting convention, where
+			 * pixel center for Cb'Cr' is between the left top and
+			 * bottom pixel in a 2x2 block, so take the average.
+			 *
+			 * Therefore, if we use subsampling, we only really care
+			 * about two pixels all the time, either the two
+			 * subsequent pixels horizontally, vertically, or the
+			 * two corners in a 2x2 block.
+			 *
+			 * The only corner case is when we have an odd number of
+			 * pixels, but this can be handled pretty easily by not
+			 * incrementing the paired pixel pointer in the
+			 * direction it's odd in.
+			 */
+			if (j != (cvt->dst.fb->width - 1))
+				pair_float += (dst_fmt->hsub - 1) * fpp;
+
+			if (i != (cvt->dst.fb->height - 1))
+				pair_float += float_stride * (dst_fmt->vsub - 1);
+
+			read_rgbf(&pair_rgb, pair_float);
+			pair_yuv = igt_matrix_transform(&m, &pair_rgb);
+
+			*u_tmp = (yuv.d[1] + pair_yuv.d[1]) / 2.0f;
+			*v_tmp = (yuv.d[2] + pair_yuv.d[2]) / 2.0f;
+
+			u_tmp += params.uv_inc;
+			v_tmp += params.uv_inc;
+		}
+
+		ptr += float_stride;
+		y += params.y_stride / sizeof(*y);
+
+		if ((i % dst_fmt->vsub) == (dst_fmt->vsub - 1)) {
+			u += params.uv_stride / sizeof(*u);
+			v += params.uv_stride / sizeof(*v);
+		}
+	}
+}
+
  static void convert_pixman(struct fb_convert *cvt)
  {
  	pixman_format_code_t src_pixman = drm_format_to_pixman(cvt->src.fb->drm_format);
@@ -1888,6 +2116,22 @@ static void fb_convert(struct fb_convert *cvt)
  			convert_rgb24_to_yuv(cvt);
  			return;
  		}
+	} else if (cvt->dst.fb->drm_format == IGT_FORMAT_FLOAT) {
+		switch (cvt->src.fb->drm_format) {
+		case DRM_FORMAT_P010:
+		case DRM_FORMAT_P012:
+		case DRM_FORMAT_P016:
+			convert_yuv16_to_float(cvt);
+			return;
+		}
+	} else if (cvt->src.fb->drm_format == IGT_FORMAT_FLOAT) {
+		switch (cvt->dst.fb->drm_format) {
+		case DRM_FORMAT_P010:
+		case DRM_FORMAT_P012:
+		case DRM_FORMAT_P016:
+			convert_float_to_yuv16(cvt);
+			return;
+		}
  	}
 
  	igt_assert_f(false,
@@ -1928,12 +2172,37 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb)
  {
  	struct fb_convert_blit_upload *blit = malloc(sizeof(*blit));
  	struct fb_convert cvt = { };
+	const struct format_desc_struct *f = lookup_drm_format(fb->drm_format);
+	unsigned drm_format;
+	cairo_format_t cairo_id;
+
+	if (f->cairo_id != CAIRO_FORMAT_INVALID) {
+		cairo_id = f->cairo_id;
+
+		switch (f->cairo_id) {
+		case CAIRO_FORMAT_RGB96F:
+		case CAIRO_FORMAT_RGBA128F:
+			drm_format = IGT_FORMAT_FLOAT;
+			break;
+		case CAIRO_FORMAT_RGB24:
+			drm_format = DRM_FORMAT_XRGB8888;
+			break;
+		default:
+			igt_assert_f(0, "Unsupported format %u", f->cairo_id);
+		}
+	} else if (PIXMAN_FORMAT_A(f->pixman_id)) {
+		cairo_id = CAIRO_FORMAT_ARGB32;
+		drm_format = DRM_FORMAT_ARGB8888;
+	} else {
+		cairo_id = CAIRO_FORMAT_RGB24;
+		drm_format = DRM_FORMAT_XRGB8888;
+	}
 
  	igt_assert(blit);
 
  	blit->base.fd = fd;
  	blit->base.fb = fb;
-	blit->shadow_ptr = igt_fb_create_cairo_shadow_buffer(fd,
+	blit->shadow_ptr = igt_fb_create_cairo_shadow_buffer(fd, drm_format,
  							     fb->width,
  							     fb->height,
  							     &blit->shadow_fb);
@@ -1960,7 +2229,7 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb)
 
  	fb->cairo_surface =
  		cairo_image_surface_create_for_data(blit->shadow_ptr,
-						    CAIRO_FORMAT_RGB24,
+						    cairo_id,
  						    fb->width, fb->height,
  						    blit->shadow_fb.strides[0]);
 
@@ -2025,6 +2294,21 @@ cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb)
  			create_cairo_surface__blit(fd, fb);
  		else
  			create_cairo_surface__gtt(fd, fb);
+
+		if (f->cairo_id == CAIRO_FORMAT_RGB96F ||
+		    f->cairo_id == CAIRO_FORMAT_RGBA128F) {
+			cairo_status_t status = cairo_surface_status(fb->cairo_surface);
+
+			igt_skip_on_f(status == CAIRO_STATUS_INVALID_FORMAT &&
+				      cairo_version() < CAIRO_VERSION_ENCODE(1, 17, 2),
+				      "Cairo version too old, need 1.17.2, have %s\n",
+				      cairo_version_string());
+
+			igt_skip_on_f(status == CAIRO_STATUS_NO_MEMORY &&
+				      pixman_version() < PIXMAN_VERSION_ENCODE(0, 36, 0),
+				      "Pixman version too old, need 0.36.0, have %s\n",
+				      pixman_version_string());
+		}
  	}
 
  	igt_assert(cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS);
@@ -2231,6 +2515,9 @@ bool igt_format_is_yuv(uint32_t drm_format)
  {
  	switch (drm_format) {
  	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
  	case DRM_FORMAT_YUYV:
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
lib/igt_fb.h +6 -0
index 9f027deba842..8c683db5e9ec 100644
@@ -38,6 +38,12 @@
 
  #include "igt_color_encoding.h"
 
+/*
+ * Internal format to denote a buffer compatible with pixman's
+ * floating point format. Range [0-1].
+ */
+#define IGT_FORMAT_FLOAT fourcc_code('I', 'G', 'F', 'x')
+
  /**
   * igt_fb_t:
   * @fb_id: KMS ID of the framebuffer
meson.build +0 -0
index b17e67ef7f05..356a5414226b 100644
@@ -336,3 +336,13 @@ message('=============')
  foreach str : build_info
  	message(str)
  endforeach

meson.build message('=============') · line 348

Quoted 10 lines
meson.build +10 -0
+
+if cairo.version().version_compare('<1.17.2')
+	if pixman.version().version_compare('<0.36.0')
+		warning('Pixman < 0.36.0 found, cannot test HDR formats')
+	endif
+	warning('Cairo < 1.17.2 found, cannot test HDR formats')
+elif pixman.version().version_compare('<0.36.0')
+	# Cairo 1.17.2 requires 0.36.0 to compile, but somehow it went missing?
+	error('Cairo with floating point support found, but pixman version too old')
+endif

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#3 lore raw

Re: [igt-dev] [PATCH v2 2/4] lib/igt_fb: Add support for P01x formats, v4.

Op 07-02-2019 om 12:52 schreef Juha-Pekka Heikkila:

Quoted 181 lines · Maarten Lankhorst
Quoted 171 lines

The P01x formats are planar 16 bits per component, with the unused lower bits set to 0. This means they can all be converted the same way. Only the range is slightly different, and this is handled in the color_encoding implementation.

This requires cairo 1.17.2 and pixman 0.36. This works but doesn't give extra precision. For more than 8 bits precision a few more patches are required to pixman, pending review:
https://lists.freedesktop.org/archives/pixman/2019-January/004815.html
https://lists.freedesktop.org/archives/pixman/2019-January/004809.html

Once those are merged, we will require the next pixman release for better precision.

Changes since v1:
- Add fallback color definitions when compiling on cairo version < 1.17.2.
- Skip when FB creation fails on HDR formats, instead of failing. Changes since v2:
- Complain slightly harder when pixman/cairo are out of date.
- Create a fb with alpha when converting to pixman formats with alpha.
- Oops, s/pixman_format_code_t/cairo_format_t/
Changes since v3:
- Rebase on top of upstream YUV changes.

---
  configure.ac                  |  11 +- include/drm-uapi/drm_fourcc.h |  10 ++ lib/igt_color_encoding.c      |   4 +
  lib/igt_fb.c                  | 293 +++++++++++++++++++++++++++++++++- lib/igt_fb.h                  |   6 +
  meson.build                   |  10 ++

  6 files changed, 329 insertions(+), 5 deletions(-)
configure.ac +9 -2
index b46f024f875a..a333cf8d6dbb 100644
@@ -136,10 +136,17 @@ fi
   PKG_CHECK_MODULES(XRANDR, xrandr >= 1.3, AC_DEFINE(HAVE_XRANDR, 1, [Have libXrandr]), [have_xrandr=no])
     # for testdisplay
-PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])
+PKG_CHECK_MODULES(CAIRO, [cairo >= 1.17.2], [],
+    [AC_MSG_WARN([Cairo too old, HDR formats not available. Upgrade to cairo 1.17.2])
+    PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])]
+)
   PKG_CHECK_MODULES(LIBUDEV, [libudev])
   PKG_CHECK_MODULES(GLIB, [glib-2.0])
-PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+PKG_CHECK_MODULES(PIXMAN, [pixman-1 >= 0.36.0], [], [
+    AC_MSG_WARN([Pixman too old, HDR formats not available. Upgrade to pixman 0.36.0])
+    PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+])
+
   PKG_CHECK_MODULES(GSL, [gsl], [gsl=yes], [gsl=no])
   AM_CONDITIONAL(HAVE_GSL, [test "x$gsl" = xyes])

  diff --git a/include/drm-uapi/drm_fourcc.h b/include/drm-uapi/drm_fourcc.h index 41106c835747..fe6b66ef1756 100644

include/drm-uapi/drm_fourcc.h +0 -0
@@ -195,6 +195,16 @@ extern "C" {
   #define DRM_FORMAT_NV24        fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
   #define DRM_FORMAT_NV42        fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */

  +/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [15:0] Y little endian where Pxxx indicate
+ * component xxx msb Y [xxx:16-xxx]
+ * index 1 = Cr:Cb plane, [31:0] Cr:Cb little endian [xxx:16-xxx:xxx:16-xxx]
+ */

include/drm-uapi/drm_fourcc.h +4 -0
+#define DRM_FORMAT_P010        fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane, 10 bit per channel */
+#define DRM_FORMAT_P012        fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane, 12 bit per channel */
+#define DRM_FORMAT_P016        fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane, 16 bit per channel */
+

  /*
   * 3 plane YCbCr
   * index 0: Y plane, [7:0] Y

lib/igt_color_encoding.c +4 -0
index 4cbe18e217e3..b7a12a1e07f7 100644
@@ -135,11 +135,15 @@ static const struct color_encoding_format {
       float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr;
   } formats[] = {
       { DRM_FORMAT_XRGB8888, 255.f, },
+    { IGT_FORMAT_FLOAT, 1.f, },
       { DRM_FORMAT_NV12, 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 },
+    { DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+    { DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+    { DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
   };
     static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +42 -1
index db3ae06748d1..12763cc85c86 100644
@@ -62,6 +62,20 @@
     #define PIXMAN_invalid    0
   +#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 17, 2)
+/*
+ * We need cairo 1.17.2 to use HDR formats, but the only thing added is a value
+ * to cairo_format_t.
+ *
+ * To prevent going outside the enum, make cairo_format_t an int and define
+ * ourselves.
+ */
+
+#define CAIRO_FORMAT_RGB96F (6)
+#define CAIRO_FORMAT_RGBA128F (7)
+#define cairo_format_t int
+#endif
+
   /* drm fourcc/cairo format maps */
   static const struct format_desc_struct {
       const char *name;
@@ -170,6 +184,25 @@ static const struct format_desc_struct {
         .num_planes = 1, .plane_bpp = { 16, },
         .hsub = 2, .vsub = 1,
       },
+    { .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
+      .cairo_id = CAIRO_FORMAT_RGB96F,
+      .num_planes = 2, .plane_bpp = { 16, 32 },
+      .vsub = 2, .hsub = 2,
+    },
+    { .name = "P012", .depth = -1, .drm_id = DRM_FORMAT_P012,
+      .cairo_id = CAIRO_FORMAT_RGB96F,
+      .num_planes = 2, .plane_bpp = { 16, 32 },
+      .vsub = 2, .hsub = 2,
+    },
+    { .name = "P016", .depth = -1, .drm_id = DRM_FORMAT_P016,
+      .cairo_id = CAIRO_FORMAT_RGB96F,
+      .num_planes = 2, .plane_bpp = { 16, 32 },
+      .vsub = 2, .hsub = 2,
+    },
+    { .name = "IGT-FLOAT", .depth = -1, .drm_id = IGT_FORMAT_FLOAT,
+      .cairo_id = CAIRO_FORMAT_INVALID,
+      .num_planes = 1, .plane_bpp = { 128 },
+    },
   };
   #define for_each_format(f)    \
       for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++)
@@ -520,6 +553,14 @@ static void clear_yuv_buffer(struct igt_fb *fb)
               full_range ? 0x00800080 : 0x10801080,
               fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
           break;
+    case DRM_FORMAT_P010:
+    case DRM_FORMAT_P012:
+    case DRM_FORMAT_P016:
+        wmemset(ptr, full_range ? 0 : 0x10001000,
+            fb->offsets[1] / sizeof(wchar_t));
+        wmemset(ptr + fb->offsets[1], 0x80008000,
+            fb->strides[1] * fb->plane_height[1] / sizeof(wchar_t));
+        break;
       }
         igt_fb_unmap_buffer(fb, ptr);
@@ -1496,6 +1537,7 @@ struct fb_convert_blit_upload {
   };
     static void *igt_fb_create_cairo_shadow_buffer(int fd,
+                           unsigned drm_format,
                              unsigned int width,
                              unsigned int height,
                              struct igt_fb *shadow)
@@ -1505,7 +1547,7 @@ static void *igt_fb_create_cairo_shadow_buffer(int fd,
       igt_assert(shadow);
         fb_init(shadow, fd, width, height,
-        DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+        drm_format, LOCAL_DRM_FORMAT_MOD_NONE,
           IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
         shadow->strides[0] = ALIGN(width * shadow->plane_bpp[0], 16);
@@ -1599,6 +1641,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
         switch (fb->drm_format) {
Quoted 6 lines

      case DRM_FORMAT_NV12:
+    case DRM_FORMAT_P010:
+    case DRM_FORMAT_P012:
+    case DRM_FORMAT_P016:
          params->y_inc = 1;
          params->uv_inc = 2;

Hi Maarten,

Quoted 5 lines

I was wondering if above y_inc and uv_inc for Pxxx should be 2x of those for NV12?

I noticed they're used below like "y_tmp += params.y_inc" where y_tmp is uint8_t*.

Other than this all look good to me in this patch. I don't have HW to test with so I cannot go see how it work.

Well we increase uint16_t pointers, so it worked out. Tested it myself for P010, didn't test the Y21x Y41x formats but should be correct. :)

~Maarten

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#4 lore raw

Re: [igt-dev] [PATCH v2 2/4] lib/igt_fb: Add support for P01x formats, v4.

Quoted 182 lines · Maarten Lankhorst

Op 07-02-2019 om 12:52 schreef Juha-Pekka Heikkila:

Quoted 181 lines · Maarten Lankhorst
Quoted 170 lines

The P01x formats are planar 16 bits per component, with the unused lower bits set to 0. This means they can all be converted the same way. Only the range is slightly different, and this is handled in the color_encoding implementation.

This requires cairo 1.17.2 and pixman 0.36. This works but doesn't give extra precision. For more than 8 bits precision a few more patches are required to pixman, pending review:
https://lists.freedesktop.org/archives/pixman/2019-January/004815.html
https://lists.freedesktop.org/archives/pixman/2019-January/004809.html

Once those are merged, we will require the next pixman release for better precision.

Changes since v1:
- Add fallback color definitions when compiling on cairo version < 1.17.2.
- Skip when FB creation fails on HDR formats, instead of failing. Changes since v2:
- Complain slightly harder when pixman/cairo are out of date.
- Create a fb with alpha when converting to pixman formats with alpha.
- Oops, s/pixman_format_code_t/cairo_format_t/
Changes since v3:
- Rebase on top of upstream YUV changes.

---
   configure.ac                  |  11 +-
   include/drm-uapi/drm_fourcc.h |  10 ++
   lib/igt_color_encoding.c      |   4 +
   lib/igt_fb.c                  | 293 +++++++++++++++++++++++++++++++++-
   lib/igt_fb.h                  |   6 +
   meson.build                   |  10 ++
   6 files changed, 329 insertions(+), 5 deletions(-)
configure.ac +9 -2
index b46f024f875a..a333cf8d6dbb 100644
@@ -136,10 +136,17 @@ fi
   PKG_CHECK_MODULES(XRANDR, xrandr >= 1.3, AC_DEFINE(HAVE_XRANDR, 1, [Have libXrandr]), [have_xrandr=no])
     # for testdisplay
-PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])
+PKG_CHECK_MODULES(CAIRO, [cairo >= 1.17.2], [],
+    [AC_MSG_WARN([Cairo too old, HDR formats not available. Upgrade to cairo 1.17.2])
+    PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])]
+)
   PKG_CHECK_MODULES(LIBUDEV, [libudev])
   PKG_CHECK_MODULES(GLIB, [glib-2.0])
-PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+PKG_CHECK_MODULES(PIXMAN, [pixman-1 >= 0.36.0], [], [
+    AC_MSG_WARN([Pixman too old, HDR formats not available. Upgrade to pixman 0.36.0])
+    PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+])
+
   PKG_CHECK_MODULES(GSL, [gsl], [gsl=yes], [gsl=no])
   AM_CONDITIONAL(HAVE_GSL, [test "x$gsl" = xyes])
   diff --git a/include/drm-uapi/drm_fourcc.h b/include/drm-uapi/drm_fourcc.h

index 41106c835747..fe6b66ef1756 100644

include/drm-uapi/drm_fourcc.h +9 -0
@@ -195,6 +195,16 @@ extern "C" {
   #define DRM_FORMAT_NV24        fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
   #define DRM_FORMAT_NV42        fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
   +/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [15:0] Y little endian where Pxxx indicate
+ * component xxx msb Y [xxx:16-xxx]
+ * index 1 = Cr:Cb plane, [31:0] Cr:Cb little endian [xxx:16-xxx:xxx:16-xxx]
+ */
+#define DRM_FORMAT_P010        fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane, 10 bit per channel */
+#define DRM_FORMAT_P012        fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane, 12 bit per channel */
+#define DRM_FORMAT_P016        fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane, 16 bit per channel */
+
   /*
    * 3 plane YCbCr
    * index 0: Y plane, [7:0] Y
lib/igt_color_encoding.c +4 -0
index 4cbe18e217e3..b7a12a1e07f7 100644
@@ -135,11 +135,15 @@ static const struct color_encoding_format {
       float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr;
   } formats[] = {
       { DRM_FORMAT_XRGB8888, 255.f, },
+    { IGT_FORMAT_FLOAT, 1.f, },
       { DRM_FORMAT_NV12, 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 },
+    { DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+    { DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+    { DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
   };
     static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +42 -1
index db3ae06748d1..12763cc85c86 100644
@@ -62,6 +62,20 @@
     #define PIXMAN_invalid    0
   +#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 17, 2)
+/*
+ * We need cairo 1.17.2 to use HDR formats, but the only thing added is a value
+ * to cairo_format_t.
+ *
+ * To prevent going outside the enum, make cairo_format_t an int and define
+ * ourselves.
+ */
+
+#define CAIRO_FORMAT_RGB96F (6)
+#define CAIRO_FORMAT_RGBA128F (7)
+#define cairo_format_t int
+#endif
+
   /* drm fourcc/cairo format maps */
   static const struct format_desc_struct {
       const char *name;
@@ -170,6 +184,25 @@ static const struct format_desc_struct {
         .num_planes = 1, .plane_bpp = { 16, },
         .hsub = 2, .vsub = 1,
       },
+    { .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
+      .cairo_id = CAIRO_FORMAT_RGB96F,
+      .num_planes = 2, .plane_bpp = { 16, 32 },
+      .vsub = 2, .hsub = 2,
+    },
+    { .name = "P012", .depth = -1, .drm_id = DRM_FORMAT_P012,
+      .cairo_id = CAIRO_FORMAT_RGB96F,
+      .num_planes = 2, .plane_bpp = { 16, 32 },
+      .vsub = 2, .hsub = 2,
+    },
+    { .name = "P016", .depth = -1, .drm_id = DRM_FORMAT_P016,
+      .cairo_id = CAIRO_FORMAT_RGB96F,
+      .num_planes = 2, .plane_bpp = { 16, 32 },
+      .vsub = 2, .hsub = 2,
+    },
+    { .name = "IGT-FLOAT", .depth = -1, .drm_id = IGT_FORMAT_FLOAT,
+      .cairo_id = CAIRO_FORMAT_INVALID,
+      .num_planes = 1, .plane_bpp = { 128 },
+    },
   };
   #define for_each_format(f)    \
       for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++)
@@ -520,6 +553,14 @@ static void clear_yuv_buffer(struct igt_fb *fb)
               full_range ? 0x00800080 : 0x10801080,
               fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
           break;
+    case DRM_FORMAT_P010:
+    case DRM_FORMAT_P012:
+    case DRM_FORMAT_P016:
+        wmemset(ptr, full_range ? 0 : 0x10001000,
+            fb->offsets[1] / sizeof(wchar_t));
+        wmemset(ptr + fb->offsets[1], 0x80008000,
+            fb->strides[1] * fb->plane_height[1] / sizeof(wchar_t));
+        break;
       }
         igt_fb_unmap_buffer(fb, ptr);
@@ -1496,6 +1537,7 @@ struct fb_convert_blit_upload {
   };
     static void *igt_fb_create_cairo_shadow_buffer(int fd,
+                           unsigned drm_format,
                              unsigned int width,
                              unsigned int height,
                              struct igt_fb *shadow)
@@ -1505,7 +1547,7 @@ static void *igt_fb_create_cairo_shadow_buffer(int fd,
       igt_assert(shadow);
         fb_init(shadow, fd, width, height,
-        DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+        drm_format, LOCAL_DRM_FORMAT_MOD_NONE,
           IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
         shadow->strides[0] = ALIGN(width * shadow->plane_bpp[0], 16);

lib/igt_fb.c static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params) · line 1647

Quoted 7 lines
lib/igt_fb.c +3 -0
@@ -1599,6 +1641,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
         switch (fb->drm_format) {
       case DRM_FORMAT_NV12:
+    case DRM_FORMAT_P010:
+    case DRM_FORMAT_P012:
+    case DRM_FORMAT_P016:
           params->y_inc = 1;
           params->uv_inc = 2;

Hi Maarten,

Quoted 7 lines
Quoted 5 lines

I was wondering if above y_inc and uv_inc for Pxxx should be 2x of those for NV12?

I noticed they're used below like "y_tmp += params.y_inc" where y_tmp is uint8_t*.

Other than this all look good to me in this patch. I don't have HW to test with so I cannot go see how it work.

Well we increase uint16_t pointers, so it worked out. Tested it myself for P010, didn't test the Y21x Y41x formats but should be correct. :)

Ah, now I got it. I was looking just at first instance where the call was made to get those parameters.

This patch is

/Juha-Pekka

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#5 lore raw

Re: [igt-dev] [PATCH v2 2/4] lib/igt_fb: Add support for P01x formats, v4.

In reply to Maarten Lankhorst

Tested V4 P0xx pixel formats on ICL U h/w. Working fine for HDR planes. SDR planes having CRC mismatch for all the YUV formats.

Quoted 531 lines · Maarten Lankhorst

The P01x formats are planar 16 bits per component, with the unused lower bits set to 0. This means they can all be converted the same way. Only the range is slightly different, and this is handled in the color_encoding implementation.

This requires cairo 1.17.2 and pixman 0.36. This works but doesn't give extra precision. For more than 8 bits precision a few more patches are required to pixman, pending review:
https://lists.freedesktop.org/archives/pixman/2019-January/004815.html
https://lists.freedesktop.org/archives/pixman/2019-January/004809.html

Once those are merged, we will require the next pixman release for better precision.

Changes since v1:
- Add fallback color definitions when compiling on cairo version < 1.17.2.
- Skip when FB creation fails on HDR formats, instead of failing. Changes since v2:
- Complain slightly harder when pixman/cairo are out of date.
- Create a fb with alpha when converting to pixman formats with alpha.
- Oops, s/pixman_format_code_t/cairo_format_t/
Changes since v3:
- Rebase on top of upstream YUV changes.

---
  configure.ac                  |  11 +-
  include/drm-uapi/drm_fourcc.h |  10 ++
  lib/igt_color_encoding.c      |   4 +
  lib/igt_fb.c                  | 293 +++++++++++++++++++++++++++++++++-
  lib/igt_fb.h                  |   6 +
  meson.build                   |  10 ++
  6 files changed, 329 insertions(+), 5 deletions(-)
configure.ac +9 -2
index b46f024f875a..a333cf8d6dbb 100644
@@ -136,10 +136,17 @@ fi
  PKG_CHECK_MODULES(XRANDR, xrandr >= 1.3, AC_DEFINE(HAVE_XRANDR, 1, [Have libXrandr]), [have_xrandr=no])
 
  # for testdisplay
-PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])
+PKG_CHECK_MODULES(CAIRO, [cairo >= 1.17.2], [],
+	[AC_MSG_WARN([Cairo too old, HDR formats not available. Upgrade to cairo 1.17.2])
+	PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])]
+)
  PKG_CHECK_MODULES(LIBUDEV, [libudev])
  PKG_CHECK_MODULES(GLIB, [glib-2.0])
-PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+PKG_CHECK_MODULES(PIXMAN, [pixman-1 >= 0.36.0], [], [
+	AC_MSG_WARN([Pixman too old, HDR formats not available. Upgrade to pixman 0.36.0])
+	PKG_CHECK_MODULES(PIXMAN, [pixman-1])
+])
+
  PKG_CHECK_MODULES(GSL, [gsl], [gsl=yes], [gsl=no])
  AM_CONDITIONAL(HAVE_GSL, [test "x$gsl" = xyes])
 
include/drm-uapi/drm_fourcc.h +10 -0
index 41106c835747..fe6b66ef1756 100644
@@ -195,6 +195,16 @@ extern "C" {
  #define DRM_FORMAT_NV24		fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
  #define DRM_FORMAT_NV42		fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
 
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [15:0] Y little endian where Pxxx indicate
+ * component xxx msb Y [xxx:16-xxx]
+ * index 1 = Cr:Cb plane, [31:0] Cr:Cb little endian [xxx:16-xxx:xxx:16-xxx]
+ */
+#define DRM_FORMAT_P010		fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane, 10 bit per channel */
+#define DRM_FORMAT_P012		fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane, 12 bit per channel */
+#define DRM_FORMAT_P016		fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane, 16 bit per channel */
+
  /*
   * 3 plane YCbCr
   * index 0: Y plane, [7:0] Y
lib/igt_color_encoding.c +4 -0
index 4cbe18e217e3..b7a12a1e07f7 100644
@@ -135,11 +135,15 @@ static const struct color_encoding_format {
  	float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr;
  } formats[] = {
  	{ DRM_FORMAT_XRGB8888, 255.f, },
+	{ IGT_FORMAT_FLOAT, 1.f, },
  	{ DRM_FORMAT_NV12, 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 },
+	{ DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  };
 
  static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +290 -3
index db3ae06748d1..12763cc85c86 100644
@@ -62,6 +62,20 @@
 
  #define PIXMAN_invalid	0
 
+#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 17, 2)
+/*
+ * We need cairo 1.17.2 to use HDR formats, but the only thing added is a value
+ * to cairo_format_t.
+ *
+ * To prevent going outside the enum, make cairo_format_t an int and define
+ * ourselves.
+ */
+
+#define CAIRO_FORMAT_RGB96F (6)
+#define CAIRO_FORMAT_RGBA128F (7)
+#define cairo_format_t int
+#endif
+
  /* drm fourcc/cairo format maps */
  static const struct format_desc_struct {
  	const char *name;
@@ -170,6 +184,25 @@ static const struct format_desc_struct {
  	  .num_planes = 1, .plane_bpp = { 16, },
  	  .hsub = 2, .vsub = 1,
  	},
+	{ .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 2, .plane_bpp = { 16, 32 },
+	  .vsub = 2, .hsub = 2,
+	},
+	{ .name = "P012", .depth = -1, .drm_id = DRM_FORMAT_P012,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 2, .plane_bpp = { 16, 32 },
+	  .vsub = 2, .hsub = 2,
+	},
+	{ .name = "P016", .depth = -1, .drm_id = DRM_FORMAT_P016,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 2, .plane_bpp = { 16, 32 },
+	  .vsub = 2, .hsub = 2,
+	},
+	{ .name = "IGT-FLOAT", .depth = -1, .drm_id = IGT_FORMAT_FLOAT,
+	  .cairo_id = CAIRO_FORMAT_INVALID,
+	  .num_planes = 1, .plane_bpp = { 128 },
+	},
  };
  #define for_each_format(f)	\
  	for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++)
@@ -520,6 +553,14 @@ static void clear_yuv_buffer(struct igt_fb *fb)
  			full_range ? 0x00800080 : 0x10801080,
  			fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
  		break;
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		wmemset(ptr, full_range ? 0 : 0x10001000,
+			fb->offsets[1] / sizeof(wchar_t));
+		wmemset(ptr + fb->offsets[1], 0x80008000,
+			fb->strides[1] * fb->plane_height[1] / sizeof(wchar_t));
+		break;
  	}
 
  	igt_fb_unmap_buffer(fb, ptr);
@@ -1496,6 +1537,7 @@ struct fb_convert_blit_upload {
  };
 
  static void *igt_fb_create_cairo_shadow_buffer(int fd,
+					       unsigned drm_format,
  					       unsigned int width,
  					       unsigned int height,
  					       struct igt_fb *shadow)
@@ -1505,7 +1547,7 @@ static void *igt_fb_create_cairo_shadow_buffer(int fd,
  	igt_assert(shadow);
 
  	fb_init(shadow, fd, width, height,
-		DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+		drm_format, LOCAL_DRM_FORMAT_MOD_NONE,
  		IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
 
  	shadow->strides[0] = ALIGN(width * shadow->plane_bpp[0], 16);
@@ -1599,6 +1641,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
 
  	switch (fb->drm_format) {
  	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
  		params->y_inc = 1;
  		params->uv_inc = 2;
  		break;
@@ -1619,6 +1664,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
 
  	switch (fb->drm_format) {
  	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
  		params->y_stride = fb->strides[0];
  		params->uv_stride = fb->strides[1];
  		break;
@@ -1640,6 +1688,14 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  		params->v_offset = fb->offsets[1] + 1;
  		break;
 
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
+		params->y_offset = fb->offsets[0];
+		params->u_offset = fb->offsets[1];
+		params->v_offset = fb->offsets[1] + 2;
+		break;
+
  	case DRM_FORMAT_YUYV:
  		params->y_offset = fb->offsets[0];
  		params->u_offset = fb->offsets[0] + 1;
@@ -1821,6 +1877,178 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt)
  	}
  }
 
+static void read_rgbf(struct igt_vec4 *rgb, const float *rgb24)
+{
+	rgb->d[0] = rgb24[0];
+	rgb->d[1] = rgb24[1];
+	rgb->d[2] = rgb24[2];
+	rgb->d[3] = 1.0f;
+}
+
+static void write_rgbf(float *rgb24, const struct igt_vec4 *rgb)
+{
+	rgb24[0] = rgb->d[0];
+	rgb24[1] = rgb->d[1];
+	rgb24[2] = rgb->d[2];
+}
+
+static void convert_yuv16_to_float(struct fb_convert *cvt)
+{
+	const struct format_desc_struct *src_fmt =
+		lookup_drm_format(cvt->src.fb->drm_format);
+	int i, j;
+	uint8_t fpp = 3;
+	uint16_t *y, *u, *v;
+	float *ptr = cvt->dst.ptr;
+	unsigned int float_stride = cvt->dst.fb->strides[0] / sizeof(*ptr);
+	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);
+	uint16_t *buf;
+	struct yuv_parameters params = { };
+
+	igt_assert(cvt->dst.fb->drm_format == IGT_FORMAT_FLOAT &&
+		   igt_format_is_yuv(cvt->src.fb->drm_format));
+
+	buf = convert_src_get(cvt);
+	get_yuv_parameters(cvt->src.fb, &params);
+	igt_assert(!(params.y_offset % sizeof(*buf)) &&
+		   !(params.u_offset % sizeof(*buf)) &&
+		   !(params.v_offset % sizeof(*buf)));
+
+	y = buf + params.y_offset / sizeof(*buf);
+	u = buf + params.u_offset / sizeof(*buf);
+	v = buf + params.v_offset / sizeof(*buf);
+
+	for (i = 0; i < cvt->dst.fb->height; i++) {
+		const uint16_t *y_tmp = y;
+		const uint16_t *u_tmp = u;
+		const uint16_t *v_tmp = v;
+		float *rgb_tmp = ptr;
+
+		for (j = 0; j < cvt->dst.fb->width; j++) {
+			struct igt_vec4 rgb, yuv;
+
+			yuv.d[0] = *y_tmp;
+			yuv.d[1] = *u_tmp;
+			yuv.d[2] = *v_tmp;
+			yuv.d[3] = 1.0f;
+
+			rgb = igt_matrix_transform(&m, &yuv);
+			write_rgbf(rgb_tmp, &rgb);
+
+			rgb_tmp += fpp;
+			y_tmp += params.y_inc;
+
+			if ((src_fmt->hsub == 1) || (j % src_fmt->hsub)) {
+				u_tmp += params.uv_inc;
+				v_tmp += params.uv_inc;
+			}
+		}
+
+		ptr += float_stride;
+		y += params.y_stride / sizeof(*y);
+
+		if ((src_fmt->vsub == 1) || (i % src_fmt->vsub)) {
+			u += params.uv_stride / sizeof(*u);
+			v += params.uv_stride / sizeof(*v);
+		}
+	}
+
+	convert_src_put(cvt, buf);
+}
+
+static void convert_float_to_yuv16(struct fb_convert *cvt)
+{
+	const struct format_desc_struct *dst_fmt =
+		lookup_drm_format(cvt->dst.fb->drm_format);
+	int i, j;
+	uint16_t *y, *u, *v;
+	const float *ptr = cvt->src.ptr;
+	uint8_t fpp = 3;
+	unsigned float_stride = cvt->src.fb->strides[0] / sizeof(*ptr);
+	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 = { };
+
+	igt_assert(cvt->src.fb->drm_format == IGT_FORMAT_FLOAT &&
+		   igt_format_is_yuv(cvt->dst.fb->drm_format));
+
+	get_yuv_parameters(cvt->dst.fb, &params);
+	igt_assert(!(params.y_offset % sizeof(*y)) &&
+		   !(params.u_offset % sizeof(*u)) &&
+		   !(params.v_offset % sizeof(*v)));
+
+	y = cvt->dst.ptr + params.y_offset;
+	u = cvt->dst.ptr + params.u_offset;
+	v = cvt->dst.ptr + params.v_offset;
+
+	for (i = 0; i < cvt->dst.fb->height; i++) {
+		const float *rgb_tmp = ptr;
+		uint16_t *y_tmp = y;
+		uint16_t *u_tmp = u;
+		uint16_t *v_tmp = v;
+
+		for (j = 0; j < cvt->dst.fb->width; j++) {
+			const float *pair_float = rgb_tmp;
+			struct igt_vec4 pair_rgb, rgb;
+			struct igt_vec4 pair_yuv, yuv;
+
+			read_rgbf(&rgb, rgb_tmp);
+			yuv = igt_matrix_transform(&m, &rgb);
+
+			rgb_tmp += fpp;
+
+			*y_tmp = yuv.d[0];
+			y_tmp += params.y_inc;
+
+			if ((i % dst_fmt->vsub) || (j % dst_fmt->hsub))
+				continue;
+
+			/*
+			 * We assume the MPEG2 chroma siting convention, where
+			 * pixel center for Cb'Cr' is between the left top and
+			 * bottom pixel in a 2x2 block, so take the average.
+			 *
+			 * Therefore, if we use subsampling, we only really care
+			 * about two pixels all the time, either the two
+			 * subsequent pixels horizontally, vertically, or the
+			 * two corners in a 2x2 block.
+			 *
+			 * The only corner case is when we have an odd number of
+			 * pixels, but this can be handled pretty easily by not
+			 * incrementing the paired pixel pointer in the
+			 * direction it's odd in.
+			 */
+			if (j != (cvt->dst.fb->width - 1))
+				pair_float += (dst_fmt->hsub - 1) * fpp;
+
+			if (i != (cvt->dst.fb->height - 1))
+				pair_float += float_stride * (dst_fmt->vsub - 1);
+
+			read_rgbf(&pair_rgb, pair_float);
+			pair_yuv = igt_matrix_transform(&m, &pair_rgb);
+
+			*u_tmp = (yuv.d[1] + pair_yuv.d[1]) / 2.0f;
+			*v_tmp = (yuv.d[2] + pair_yuv.d[2]) / 2.0f;
+
+			u_tmp += params.uv_inc;
+			v_tmp += params.uv_inc;
+		}
+
+		ptr += float_stride;
+		y += params.y_stride / sizeof(*y);
+
+		if ((i % dst_fmt->vsub) == (dst_fmt->vsub - 1)) {
+			u += params.uv_stride / sizeof(*u);
+			v += params.uv_stride / sizeof(*v);
+		}
+	}
+}
+
  static void convert_pixman(struct fb_convert *cvt)
  {
  	pixman_format_code_t src_pixman = drm_format_to_pixman(cvt->src.fb->drm_format);
@@ -1888,6 +2116,22 @@ static void fb_convert(struct fb_convert *cvt)
  			convert_rgb24_to_yuv(cvt);
  			return;
  		}
+	} else if (cvt->dst.fb->drm_format == IGT_FORMAT_FLOAT) {
+		switch (cvt->src.fb->drm_format) {
+		case DRM_FORMAT_P010:
+		case DRM_FORMAT_P012:
+		case DRM_FORMAT_P016:
+			convert_yuv16_to_float(cvt);
+			return;
+		}
+	} else if (cvt->src.fb->drm_format == IGT_FORMAT_FLOAT) {
+		switch (cvt->dst.fb->drm_format) {
+		case DRM_FORMAT_P010:
+		case DRM_FORMAT_P012:
+		case DRM_FORMAT_P016:
+			convert_float_to_yuv16(cvt);
+			return;
+		}
  	}
 
  	igt_assert_f(false,
@@ -1928,12 +2172,37 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb)
  {
  	struct fb_convert_blit_upload *blit = malloc(sizeof(*blit));
  	struct fb_convert cvt = { };
+	const struct format_desc_struct *f = lookup_drm_format(fb->drm_format);
+	unsigned drm_format;
+	cairo_format_t cairo_id;
+
+	if (f->cairo_id != CAIRO_FORMAT_INVALID) {
+		cairo_id = f->cairo_id;
+
+		switch (f->cairo_id) {
+		case CAIRO_FORMAT_RGB96F:
+		case CAIRO_FORMAT_RGBA128F:
+			drm_format = IGT_FORMAT_FLOAT;
+			break;
+		case CAIRO_FORMAT_RGB24:
+			drm_format = DRM_FORMAT_XRGB8888;
+			break;
+		default:
+			igt_assert_f(0, "Unsupported format %u", f->cairo_id);
+		}
+	} else if (PIXMAN_FORMAT_A(f->pixman_id)) {
+		cairo_id = CAIRO_FORMAT_ARGB32;
+		drm_format = DRM_FORMAT_ARGB8888;
+	} else {
+		cairo_id = CAIRO_FORMAT_RGB24;
+		drm_format = DRM_FORMAT_XRGB8888;
+	}
 
  	igt_assert(blit);
 
  	blit->base.fd = fd;
  	blit->base.fb = fb;
-	blit->shadow_ptr = igt_fb_create_cairo_shadow_buffer(fd,
+	blit->shadow_ptr = igt_fb_create_cairo_shadow_buffer(fd, drm_format,
  							     fb->width,
  							     fb->height,
  							     &blit->shadow_fb);
@@ -1960,7 +2229,7 @@ static void create_cairo_surface__convert(int fd, struct igt_fb *fb)
 
  	fb->cairo_surface =
  		cairo_image_surface_create_for_data(blit->shadow_ptr,
-						    CAIRO_FORMAT_RGB24,
+						    cairo_id,
  						    fb->width, fb->height,
  						    blit->shadow_fb.strides[0]);
 
@@ -2025,6 +2294,21 @@ cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb)
  			create_cairo_surface__blit(fd, fb);
  		else
  			create_cairo_surface__gtt(fd, fb);
+
+		if (f->cairo_id == CAIRO_FORMAT_RGB96F ||
+		    f->cairo_id == CAIRO_FORMAT_RGBA128F) {
+			cairo_status_t status = cairo_surface_status(fb->cairo_surface);
+
+			igt_skip_on_f(status == CAIRO_STATUS_INVALID_FORMAT &&
+				      cairo_version() < CAIRO_VERSION_ENCODE(1, 17, 2),
+				      "Cairo version too old, need 1.17.2, have %s\n",
+				      cairo_version_string());
+
+			igt_skip_on_f(status == CAIRO_STATUS_NO_MEMORY &&
+				      pixman_version() < PIXMAN_VERSION_ENCODE(0, 36, 0),
+				      "Pixman version too old, need 0.36.0, have %s\n",
+				      pixman_version_string());
+		}
  	}
 
  	igt_assert(cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS);
@@ -2231,6 +2515,9 @@ bool igt_format_is_yuv(uint32_t drm_format)
  {
  	switch (drm_format) {
  	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_P010:
+	case DRM_FORMAT_P012:
+	case DRM_FORMAT_P016:
  	case DRM_FORMAT_YUYV:
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
lib/igt_fb.h +6 -0
index 9f027deba842..8c683db5e9ec 100644
@@ -38,6 +38,12 @@
 
  #include "igt_color_encoding.h"
 
+/*
+ * Internal format to denote a buffer compatible with pixman's
+ * floating point format. Range [0-1].
+ */
+#define IGT_FORMAT_FLOAT fourcc_code('I', 'G', 'F', 'x')
+
  /**
   * igt_fb_t:
   * @fb_id: KMS ID of the framebuffer
meson.build +10 -0
index b17e67ef7f05..356a5414226b 100644
@@ -336,3 +336,13 @@ message('=============')
  foreach str : build_info
  	message(str)
  endforeach
+
+if cairo.version().version_compare('<1.17.2')
+	if pixman.version().version_compare('<0.36.0')
+		warning('Pixman < 0.36.0 found, cannot test HDR formats')
+	endif
+	warning('Cairo < 1.17.2 found, cannot test HDR formats')
+elif pixman.version().version_compare('<0.36.0')
+	# Cairo 1.17.2 requires 0.36.0 to compile, but somehow it went missing?
+	error('Cairo with floating point support found, but pixman version too old')
+endif
Signature · 1 line
~Swati Sharma

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#6 lore raw

PATCH v2 3/4 lib/igt_fb: Add support for Y21x formats as well, v2.

In reply to Maarten Lankhorst

Those formats are packed like YUYV, but only 16 bits per component.

Changes since v1:
- Rebase on top of upstream YUV changes.

---
 include/drm-uapi/drm_fourcc.h |  6 ++++-
 lib/igt_color_encoding.c      |  3 +++
 lib/igt_fb.c                  | 46 +++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 1 deletion(-)
include/drm-uapi/drm_fourcc.h +5 -1
index fe6b66ef1756..ff9ea02766ee 100644
@@ -149,10 +149,14 @@ extern "C" {
 #define DRM_FORMAT_YVYU		fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
 #define DRM_FORMAT_UYVY		fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
 #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 */
 
+/* Like YUYV, but 16 bpc, lowest bits unused like in DRM_FORMAT_P01X */
+#define DRM_FORMAT_Y210		fourcc_code('Y', '2', '1', '0')
+#define DRM_FORMAT_Y212		fourcc_code('Y', '2', '1', '2')
+#define DRM_FORMAT_Y216		fourcc_code('Y', '2', '1', '6')
+
 /*
  * packed YCbCr420 2x2 tiled formats
  * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
lib/igt_color_encoding.c +3 -0
index b7a12a1e07f7..6f82fcec62e4 100644
@@ -144,6 +144,9 @@ static const struct color_encoding_format {
 	{ DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 	{ DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 	{ DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y210, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y212, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y216, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 };
 
 static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +46 -0

94 lines not on this page · raw message

Signature · 6 lines
2.20.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
Reviewed-by on v2 3/4
#7 lore raw

Re: [igt-dev] [PATCH v2 3/4] lib/igt_fb: Add support for Y21x formats as well, v2.

Quoted 144 lines · Maarten Lankhorst

Those formats are packed like YUYV, but only 16 bits per component.

Changes since v1:
- Rebase on top of upstream YUV changes.

---
  include/drm-uapi/drm_fourcc.h |  6 ++++-
  lib/igt_color_encoding.c      |  3 +++
  lib/igt_fb.c                  | 46 +++++++++++++++++++++++++++++++++++
  3 files changed, 54 insertions(+), 1 deletion(-)
include/drm-uapi/drm_fourcc.h +5 -1
index fe6b66ef1756..ff9ea02766ee 100644
@@ -149,10 +149,14 @@ extern "C" {
  #define DRM_FORMAT_YVYU		fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
  #define DRM_FORMAT_UYVY		fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
  #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 */
 
+/* Like YUYV, but 16 bpc, lowest bits unused like in DRM_FORMAT_P01X */
+#define DRM_FORMAT_Y210		fourcc_code('Y', '2', '1', '0')
+#define DRM_FORMAT_Y212		fourcc_code('Y', '2', '1', '2')
+#define DRM_FORMAT_Y216		fourcc_code('Y', '2', '1', '6')
+
  /*
   * packed YCbCr420 2x2 tiled formats
   * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
lib/igt_color_encoding.c +3 -0
index b7a12a1e07f7..6f82fcec62e4 100644
@@ -144,6 +144,9 @@ static const struct color_encoding_format {
  	{ DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y210, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y212, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y216, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  };
 
  static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +43 -0
index 12763cc85c86..cccd6bb98395 100644
@@ -184,6 +184,21 @@ static const struct format_desc_struct {
  	  .num_planes = 1, .plane_bpp = { 16, },
  	  .hsub = 2, .vsub = 1,
  	},
+	{ .name = "Y210", .depth = -1, .drm_id = DRM_FORMAT_Y210,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 2, .vsub = 1,
+	},
+	{ .name = "Y212", .depth = -1, .drm_id = DRM_FORMAT_Y212,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 2, .vsub = 1,
+	},
+	{ .name = "Y216", .depth = -1, .drm_id = DRM_FORMAT_Y216,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 2, .vsub = 1,
+	},
  	{ .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
  	  .cairo_id = CAIRO_FORMAT_RGB96F,
  	  .num_planes = 2, .plane_bpp = { 16, 32 },
@@ -561,6 +576,14 @@ static void clear_yuv_buffer(struct igt_fb *fb)
  		wmemset(ptr + fb->offsets[1], 0x80008000,
  			fb->strides[1] * fb->plane_height[1] / sizeof(wchar_t));
  		break;
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+		wmemset(ptr + fb->offsets[0],
+			full_range ? 0x80000000 : 0x80001000,
+			fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
+		break;
+
  	}
 
  	igt_fb_unmap_buffer(fb, ptr);
@@ -1652,6 +1675,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
  	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
  		params->y_inc = 2;
  		params->uv_inc = 4;
  		break;
@@ -1675,6 +1701,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
  	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
  	case DRM_FORMAT_XYUV8888:
  		params->y_stride = fb->strides[0];
  		params->uv_stride = fb->strides[0];
@@ -1720,6 +1749,14 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  		params->v_offset = fb->offsets[0];
  		break;
 
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+		params->y_offset = fb->offsets[0];
+		params->u_offset = fb->offsets[0] + 2;
+		params->v_offset = fb->offsets[0] + 6;
+		break;
+
  	case DRM_FORMAT_XYUV8888:
  		params->y_offset = fb->offsets[0] + 1;
  		params->u_offset = fb->offsets[0] + 2;
@@ -2121,6 +2158,9 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_P010:
  		case DRM_FORMAT_P012:
  		case DRM_FORMAT_P016:
+		case DRM_FORMAT_Y210:
+		case DRM_FORMAT_Y212:
+		case DRM_FORMAT_Y216:
  			convert_yuv16_to_float(cvt);
  			return;
  		}
@@ -2129,6 +2169,9 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_P010:
  		case DRM_FORMAT_P012:
  		case DRM_FORMAT_P016:
+		case DRM_FORMAT_Y210:
+		case DRM_FORMAT_Y212:
+		case DRM_FORMAT_Y216:
  			convert_float_to_yuv16(cvt);
  			return;
  		}

lib/igt_fb.c bool igt_format_is_yuv(uint32_t drm_format) · line 2569

Quoted 9 lines
lib/igt_fb.c +3 -0
@@ -2518,6 +2561,9 @@ bool igt_format_is_yuv(uint32_t drm_format)
  	case DRM_FORMAT_P010:
  	case DRM_FORMAT_P012:
  	case DRM_FORMAT_P016:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
  	case DRM_FORMAT_YUYV:
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#8 lore raw

Re: [igt-dev] [PATCH v2 3/4] lib/igt_fb: Add support for Y21x formats as well, v2.

In reply to Maarten Lankhorst

Tested V2 Y21x pixel formats on ICL U h/w. Working fine for HDR planes. SDR planes having CRC mismatch for all the YUV formats.

Quoted 152 lines · Maarten Lankhorst

Those formats are packed like YUYV, but only 16 bits per component.

Changes since v1:
- Rebase on top of upstream YUV changes.

---
  include/drm-uapi/drm_fourcc.h |  6 ++++-
  lib/igt_color_encoding.c      |  3 +++
  lib/igt_fb.c                  | 46 +++++++++++++++++++++++++++++++++++
  3 files changed, 54 insertions(+), 1 deletion(-)
include/drm-uapi/drm_fourcc.h +5 -1
index fe6b66ef1756..ff9ea02766ee 100644
@@ -149,10 +149,14 @@ extern "C" {
  #define DRM_FORMAT_YVYU		fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
  #define DRM_FORMAT_UYVY		fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
  #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 */
 
+/* Like YUYV, but 16 bpc, lowest bits unused like in DRM_FORMAT_P01X */
+#define DRM_FORMAT_Y210		fourcc_code('Y', '2', '1', '0')
+#define DRM_FORMAT_Y212		fourcc_code('Y', '2', '1', '2')
+#define DRM_FORMAT_Y216		fourcc_code('Y', '2', '1', '6')
+
  /*
   * packed YCbCr420 2x2 tiled formats
   * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
lib/igt_color_encoding.c +3 -0
index b7a12a1e07f7..6f82fcec62e4 100644
@@ -144,6 +144,9 @@ static const struct color_encoding_format {
  	{ DRM_FORMAT_P010, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_P012, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_P016, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y210, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y212, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y216, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  };
 
  static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +46 -0
index 12763cc85c86..cccd6bb98395 100644
@@ -184,6 +184,21 @@ static const struct format_desc_struct {
  	  .num_planes = 1, .plane_bpp = { 16, },
  	  .hsub = 2, .vsub = 1,
  	},
+	{ .name = "Y210", .depth = -1, .drm_id = DRM_FORMAT_Y210,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 2, .vsub = 1,
+	},
+	{ .name = "Y212", .depth = -1, .drm_id = DRM_FORMAT_Y212,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 2, .vsub = 1,
+	},
+	{ .name = "Y216", .depth = -1, .drm_id = DRM_FORMAT_Y216,
+	  .cairo_id = CAIRO_FORMAT_RGB96F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 2, .vsub = 1,
+	},
  	{ .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
  	  .cairo_id = CAIRO_FORMAT_RGB96F,
  	  .num_planes = 2, .plane_bpp = { 16, 32 },
@@ -561,6 +576,14 @@ static void clear_yuv_buffer(struct igt_fb *fb)
  		wmemset(ptr + fb->offsets[1], 0x80008000,
  			fb->strides[1] * fb->plane_height[1] / sizeof(wchar_t));
  		break;
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+		wmemset(ptr + fb->offsets[0],
+			full_range ? 0x80000000 : 0x80001000,
+			fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
+		break;
+
  	}
 
  	igt_fb_unmap_buffer(fb, ptr);
@@ -1652,6 +1675,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
  	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
  		params->y_inc = 2;
  		params->uv_inc = 4;
  		break;
@@ -1675,6 +1701,9 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
  	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
  	case DRM_FORMAT_XYUV8888:
  		params->y_stride = fb->strides[0];
  		params->uv_stride = fb->strides[0];
@@ -1720,6 +1749,14 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  		params->v_offset = fb->offsets[0];
  		break;
 
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
+		params->y_offset = fb->offsets[0];
+		params->u_offset = fb->offsets[0] + 2;
+		params->v_offset = fb->offsets[0] + 6;
+		break;
+
  	case DRM_FORMAT_XYUV8888:
  		params->y_offset = fb->offsets[0] + 1;
  		params->u_offset = fb->offsets[0] + 2;
@@ -2121,6 +2158,9 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_P010:
  		case DRM_FORMAT_P012:
  		case DRM_FORMAT_P016:
+		case DRM_FORMAT_Y210:
+		case DRM_FORMAT_Y212:
+		case DRM_FORMAT_Y216:
  			convert_yuv16_to_float(cvt);
  			return;
  		}
@@ -2129,6 +2169,9 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_P010:
  		case DRM_FORMAT_P012:
  		case DRM_FORMAT_P016:
+		case DRM_FORMAT_Y210:
+		case DRM_FORMAT_Y212:
+		case DRM_FORMAT_Y216:
  			convert_float_to_yuv16(cvt);
  			return;
  		}
@@ -2518,6 +2561,9 @@ bool igt_format_is_yuv(uint32_t drm_format)
  	case DRM_FORMAT_P010:
  	case DRM_FORMAT_P012:
  	case DRM_FORMAT_P016:
+	case DRM_FORMAT_Y210:
+	case DRM_FORMAT_Y212:
+	case DRM_FORMAT_Y216:
  	case DRM_FORMAT_YUYV:
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
Signature · 1 line
~Swati Sharma

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#9 lore raw

PATCH v2 4/4 lib/igt_fb: Add support for Y410/Y416 formats, v2.

In reply to Maarten Lankhorst

Y410 is packed with compressed a channel and only 32 bpp, like 10 bits RGB formats. Y416 is a packed 16 bits per component format.

Changes since v1:
- Rebase on top of upstream YUV changes.

---
 include/drm-uapi/drm_fourcc.h |   3 +
 lib/igt_color_encoding.c      |   2 +
 lib/igt_fb.c                  | 204 ++++++++++++++++++++++++++++++----
 3 files changed, 185 insertions(+), 24 deletions(-)
include/drm-uapi/drm_fourcc.h +3 -0
index ff9ea02766ee..62b4ba023a4d 100644
@@ -157,6 +157,9 @@ extern "C" {
 #define DRM_FORMAT_Y212		fourcc_code('Y', '2', '1', '2')
 #define DRM_FORMAT_Y216		fourcc_code('Y', '2', '1', '6')
 
+#define DRM_FORMAT_Y410		fourcc_code('Y', '4', '1', '0') /* [31:0] A:V:Y:U 2:10:10:10 little endian */
+#define DRM_FORMAT_Y416		fourcc_code('Y', '4', '1', '6') /* [127:0] A:V:Y:U 16:16:16:16 little endian */
+
 /*
  * packed YCbCr420 2x2 tiled formats
  * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
lib/igt_color_encoding.c +2 -0
index 6f82fcec62e4..bc9575fca1b4 100644
@@ -147,6 +147,8 @@ static const struct color_encoding_format {
 	{ DRM_FORMAT_Y210, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 	{ DRM_FORMAT_Y212, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 	{ DRM_FORMAT_Y216, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y410, 1023.f, 64.f, 940.f, 64.f, 512.f, 960.f },
+	{ DRM_FORMAT_Y416, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
 };
 
 static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +180 -24

381 lines not on this page · raw message

Signature · 6 lines
2.20.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
Reviewed-by on v2 4/4
#10 lore raw

Re: [igt-dev] [PATCH v2 4/4] lib/igt_fb: Add support for Y410/Y416 formats, v2.

This look good to me.

Quoted 442 lines · Maarten Lankhorst

Y410 is packed with compressed a channel and only 32 bpp, like 10 bits RGB formats. Y416 is a packed 16 bits per component format.

Changes since v1:
- Rebase on top of upstream YUV changes.

---
  include/drm-uapi/drm_fourcc.h |   3 +
  lib/igt_color_encoding.c      |   2 +
  lib/igt_fb.c                  | 204 ++++++++++++++++++++++++++++++----
  3 files changed, 185 insertions(+), 24 deletions(-)
include/drm-uapi/drm_fourcc.h +3 -0
index ff9ea02766ee..62b4ba023a4d 100644
@@ -157,6 +157,9 @@ extern "C" {
  #define DRM_FORMAT_Y212		fourcc_code('Y', '2', '1', '2')
  #define DRM_FORMAT_Y216		fourcc_code('Y', '2', '1', '6')
 
+#define DRM_FORMAT_Y410		fourcc_code('Y', '4', '1', '0') /* [31:0] A:V:Y:U 2:10:10:10 little endian */
+#define DRM_FORMAT_Y416		fourcc_code('Y', '4', '1', '6') /* [127:0] A:V:Y:U 16:16:16:16 little endian */
+
  /*
   * packed YCbCr420 2x2 tiled formats
   * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
lib/igt_color_encoding.c +2 -0
index 6f82fcec62e4..bc9575fca1b4 100644
@@ -147,6 +147,8 @@ static const struct color_encoding_format {
  	{ DRM_FORMAT_Y210, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_Y212, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_Y216, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y410, 1023.f, 64.f, 940.f, 64.f, 512.f, 960.f },
+	{ DRM_FORMAT_Y416, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  };
 
  static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +178 -24
index cccd6bb98395..b8c82b985fd3 100644
@@ -199,6 +199,16 @@ static const struct format_desc_struct {
  	  .num_planes = 1, .plane_bpp = { 32, },
  	  .hsub = 2, .vsub = 1,
  	},
+	{ .name = "Y410", .depth = -1, .drm_id = DRM_FORMAT_Y410,
+	  .cairo_id = CAIRO_FORMAT_RGBA128F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 1, .vsub = 1,
+	},
+	{ .name = "Y416", .depth = -1, .drm_id = DRM_FORMAT_Y416,
+	  .cairo_id = CAIRO_FORMAT_RGBA128F,
+	  .num_planes = 1, .plane_bpp = { 64, },
+	  .hsub = 1, .vsub = 1,
+	},
  	{ .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
  	  .cairo_id = CAIRO_FORMAT_RGB96F,
  	  .num_planes = 2, .plane_bpp = { 16, 32 },
@@ -584,6 +594,28 @@ static void clear_yuv_buffer(struct igt_fb *fb)
  			fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
  		break;
 
+	case DRM_FORMAT_Y410:
+		wmemset(ptr + fb->offsets[0],
+			full_range ? 0xe0000200 : 0xe0010200,
+		fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
+		break;
+	case DRM_FORMAT_Y416: {
+		struct ayuv16 { uint16_t u, y, v, a; };
+		const struct ayuv16 pixel = {
+			.a = 0xffff,
+			.v = full_range ? 0 : 0x1000,
+			.y = 0x8000,
+			.u = full_range ? 0 : 0x1000
+		};
+
+		for (int i = 0; i < fb->plane_height[0]; i++) {
+			struct ayuv16 *cur = ptr + fb->offsets[0] + fb->strides[0] * i;
+
+			for (int j = 0; i < fb->plane_width[0]; j++)
+				*cur++ = pixel;
+		}
+		break;
+		}
  	}
 
  	igt_fb_unmap_buffer(fb, ptr);
@@ -1649,10 +1681,11 @@ static void convert_src_put(const struct fb_convert *cvt,
  }
 
  struct yuv_parameters {
-	unsigned	y_inc;
+	unsigned	ay_inc;
  	unsigned	uv_inc;
-	unsigned	y_stride;
+	unsigned	ay_stride;
  	unsigned	uv_stride;
+	unsigned	a_offset;
  	unsigned	y_offset;
  	unsigned	u_offset;
  	unsigned	v_offset;
@@ -1667,7 +1700,7 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_P010:
  	case DRM_FORMAT_P012:
  	case DRM_FORMAT_P016:
-		params->y_inc = 1;
+		params->ay_inc = 1;
  		params->uv_inc = 2;
  		break;
 
@@ -1678,12 +1711,13 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_Y210:
  	case DRM_FORMAT_Y212:
  	case DRM_FORMAT_Y216:
-		params->y_inc = 2;
+		params->ay_inc = 2;
  		params->uv_inc = 4;
  		break;
 
+	case DRM_FORMAT_Y416:
  	case DRM_FORMAT_XYUV8888:
-		params->y_inc = 4;
+		params->ay_inc = 4;
  		params->uv_inc = 4;
  		break;
  	}
@@ -1693,7 +1727,7 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_P010:
  	case DRM_FORMAT_P012:
  	case DRM_FORMAT_P016:
-		params->y_stride = fb->strides[0];
+		params->ay_stride = fb->strides[0];
  		params->uv_stride = fb->strides[1];
  		break;
 
@@ -1705,7 +1739,8 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_Y212:
  	case DRM_FORMAT_Y216:
  	case DRM_FORMAT_XYUV8888:
-		params->y_stride = fb->strides[0];
+	case DRM_FORMAT_Y416:
+		params->ay_stride = fb->strides[0];
  		params->uv_stride = fb->strides[0];
  		break;
  	}
@@ -1757,6 +1792,13 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  		params->v_offset = fb->offsets[0] + 6;
  		break;
 
+	case DRM_FORMAT_Y416:
+		params->a_offset = fb->offsets[0] + 6;
+		params->y_offset = fb->offsets[0] + 2;
+		params->u_offset = fb->offsets[0];
+		params->v_offset = fb->offsets[0] + 4;
+		break;
+
  	case DRM_FORMAT_XYUV8888:
  		params->y_offset = fb->offsets[0] + 1;
  		params->u_offset = fb->offsets[0] + 2;
@@ -1808,7 +1850,7 @@ static void convert_yuv_to_rgb24(struct fb_convert *cvt)
  			write_rgb(rgb_tmp, &rgb);
 
  			rgb_tmp += bpp;
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((src_fmt->hsub == 1) || (j % src_fmt->hsub)) {
  				u_tmp += params.uv_inc;
@@ -1817,7 +1859,7 @@ static void convert_yuv_to_rgb24(struct fb_convert *cvt)
  		}
 
  		rgb24 += rgb24_stride;
-		y += params.y_stride;
+		y += params.ay_stride;
 
  		if ((src_fmt->vsub == 1) || (i % src_fmt->vsub)) {
  			u += params.uv_stride;
@@ -1868,7 +1910,7 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt)
  			rgb_tmp += bpp;
 
  			*y_tmp = yuv.d[0];
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((i % dst_fmt->vsub) || (j % dst_fmt->hsub))
  				continue;
@@ -1905,7 +1947,7 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt)
  		}
 
  		rgb24 += rgb24_stride;
-		y += params.y_stride;
+		y += params.ay_stride;
 
  		if ((i % dst_fmt->vsub) == (dst_fmt->vsub - 1)) {
  			u += params.uv_stride;
@@ -1929,13 +1971,13 @@ static void write_rgbf(float *rgb24, const struct igt_vec4 *rgb)
  	rgb24[2] = rgb->d[2];
  }
 
-static void convert_yuv16_to_float(struct fb_convert *cvt)
+static void convert_yuv16_to_float(struct fb_convert *cvt, bool alpha)
  {
  	const struct format_desc_struct *src_fmt =
  		lookup_drm_format(cvt->src.fb->drm_format);
  	int i, j;
-	uint8_t fpp = 3;
-	uint16_t *y, *u, *v;
+	uint8_t fpp = alpha ? 4 : 3;
+	uint16_t *a, *y, *u, *v;
  	float *ptr = cvt->dst.ptr;
  	unsigned int float_stride = cvt->dst.fb->strides[0] / sizeof(*ptr);
  	struct igt_mat4 m = igt_ycbcr_to_rgb_matrix(cvt->src.fb->drm_format,
@@ -1954,11 +1996,13 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  		   !(params.u_offset % sizeof(*buf)) &&
  		   !(params.v_offset % sizeof(*buf)));
 
+	a = buf + params.a_offset / sizeof(*buf);
  	y = buf + params.y_offset / sizeof(*buf);
  	u = buf + params.u_offset / sizeof(*buf);
  	v = buf + params.v_offset / sizeof(*buf);
 
  	for (i = 0; i < cvt->dst.fb->height; i++) {
+		const uint16_t *a_tmp = a;
  		const uint16_t *y_tmp = y;
  		const uint16_t *u_tmp = u;
  		const uint16_t *v_tmp = v;
@@ -1975,8 +2019,13 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  			rgb = igt_matrix_transform(&m, &yuv);
  			write_rgbf(rgb_tmp, &rgb);
 
+			if (alpha) {
+				rgb_tmp[3] = ((float)*a_tmp) / 65535.f;
+				a_tmp += params.ay_inc;
+			}
+
  			rgb_tmp += fpp;
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((src_fmt->hsub == 1) || (j % src_fmt->hsub)) {
  				u_tmp += params.uv_inc;
@@ -1985,7 +2034,9 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  		}
 
  		ptr += float_stride;
-		y += params.y_stride / sizeof(*y);
+
+		a += params.ay_stride / sizeof(*a);
+		y += params.ay_stride / sizeof(*y);
 
  		if ((src_fmt->vsub == 1) || (i % src_fmt->vsub)) {
  			u += params.uv_stride / sizeof(*u);
@@ -1996,14 +2047,14 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  	convert_src_put(cvt, buf);
  }
 
-static void convert_float_to_yuv16(struct fb_convert *cvt)
+static void convert_float_to_yuv16(struct fb_convert *cvt, bool alpha)
  {
  	const struct format_desc_struct *dst_fmt =
  		lookup_drm_format(cvt->dst.fb->drm_format);
  	int i, j;
-	uint16_t *y, *u, *v;
+	uint16_t *a, *y, *u, *v;
  	const float *ptr = cvt->src.ptr;
-	uint8_t fpp = 3;
+	uint8_t fpp = alpha ? 4 : 3;
  	unsigned float_stride = cvt->src.fb->strides[0] / sizeof(*ptr);
  	struct igt_mat4 m = igt_rgb_to_ycbcr_matrix(cvt->src.fb->drm_format,
  						    cvt->dst.fb->drm_format,
@@ -2015,16 +2066,19 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  		   igt_format_is_yuv(cvt->dst.fb->drm_format));
 
  	get_yuv_parameters(cvt->dst.fb, &params);
-	igt_assert(!(params.y_offset % sizeof(*y)) &&
+	igt_assert(!(params.a_offset % sizeof(*a)) &&
+		   !(params.y_offset % sizeof(*y)) &&
  		   !(params.u_offset % sizeof(*u)) &&
  		   !(params.v_offset % sizeof(*v)));
 
+	a = cvt->dst.ptr + params.a_offset;
  	y = cvt->dst.ptr + params.y_offset;
  	u = cvt->dst.ptr + params.u_offset;
  	v = cvt->dst.ptr + params.v_offset;
 
  	for (i = 0; i < cvt->dst.fb->height; i++) {
  		const float *rgb_tmp = ptr;
+		uint16_t *a_tmp = a;
  		uint16_t *y_tmp = y;
  		uint16_t *u_tmp = u;
  		uint16_t *v_tmp = v;
@@ -2037,10 +2091,15 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  			read_rgbf(&rgb, rgb_tmp);
  			yuv = igt_matrix_transform(&m, &rgb);
 
+			if (alpha) {
+				*a_tmp = rgb_tmp[3] * 65535.f + .5f;
+				a_tmp += params.ay_inc;
+			}
+
  			rgb_tmp += fpp;
 
  			*y_tmp = yuv.d[0];
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((i % dst_fmt->vsub) || (j % dst_fmt->hsub))
  				continue;
@@ -2077,7 +2136,8 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  		}
 
  		ptr += float_stride;
-		y += params.y_stride / sizeof(*y);
+		a += params.ay_stride / sizeof(*a);
+		y += params.ay_stride / sizeof(*y);
 
  		if ((i % dst_fmt->vsub) == (dst_fmt->vsub - 1)) {
  			u += params.uv_stride / sizeof(*u);
@@ -2086,6 +2146,88 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  	}
  }
 
+static void convert_Y410_to_float(struct fb_convert *cvt)
+{
+	int i, j;
+	const uint32_t *yuyv;
+	uint32_t *buf;
+	float *ptr = cvt->dst.ptr;
+	unsigned int float_stride = cvt->dst.fb->strides[0] / sizeof(*ptr);
+	unsigned int yuyv_stride = cvt->src.fb->strides[0] / sizeof(*yuyv);
+	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);
+
+	igt_assert(cvt->src.fb->drm_format == DRM_FORMAT_Y410 &&
+		   cvt->dst.fb->drm_format == IGT_FORMAT_FLOAT);
+
+	yuyv = buf = convert_src_get(cvt);
+
+	for (i = 0; i < cvt->dst.fb->height; i++) {
+		for (j = 0; j < cvt->dst.fb->width; j++) {
+			/* Convert 2x1 pixel blocks */
+			struct igt_vec4 yuv;
+			struct igt_vec4 rgb;
+
+			yuv.d[0] = yuyv[j] & 0x3ff;
+			yuv.d[1] = (yuyv[j] >> 10) & 0x3ff;
+			yuv.d[2] = (yuyv[j] >> 20) & 0x3ff;
+			yuv.d[3] = 1.f;
+
+			rgb = igt_matrix_transform(&m, &yuv);
+
+			write_rgbf(&ptr[j * 4 + 0], &rgb);
+			ptr[j * 4 + 3] = (float)(yuyv[j] >> 30) / 3;
+		}
+
+		ptr += float_stride;
+		yuyv += yuyv_stride;
+	}
+
+	convert_src_put(cvt, buf);
+}
+
+static void convert_float_to_Y410(struct fb_convert *cvt)
+{
+	int i, j;
+	uint32_t *yuyv = cvt->dst.ptr;
+	const float *ptr = cvt->src.ptr;
+	unsigned float_stride = cvt->src.fb->strides[0] / sizeof(*ptr);
+	unsigned yuyv_stride = cvt->dst.fb->strides[0] / sizeof(*yuyv);
+	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);
+
+	igt_assert(cvt->src.fb->drm_format == IGT_FORMAT_FLOAT &&
+		   cvt->dst.fb->drm_format == DRM_FORMAT_Y410);
+
+	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;
+			uint8_t alpha = ptr[j * 4 + 3] * 3.f + .5f;
+			uint16_t y, cb, cr;
+
+			read_rgbf(&rgb, &ptr[j * 4 + 0]);
+
+			yuv = igt_matrix_transform(&m, &rgb);
+			cr = yuv.d[0];
+			y = yuv.d[1];
+			cb = yuv.d[2];
+
+			yuyv[j] = ((cr & 0x3ff) << 0) |
+				  ((y & 0x3ff) << 10) |
+				  ((cb & 0x3ff) << 20) |
+				  (alpha << 30);
+		}
+
+		ptr += float_stride;
+		yuyv += yuyv_stride;
+	}
+}
+
  static void convert_pixman(struct fb_convert *cvt)
  {
  	pixman_format_code_t src_pixman = drm_format_to_pixman(cvt->src.fb->drm_format);
@@ -2161,7 +2303,13 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_Y210:
  		case DRM_FORMAT_Y212:
  		case DRM_FORMAT_Y216:
-			convert_yuv16_to_float(cvt);
+			convert_yuv16_to_float(cvt, false);
+			return;
+		case DRM_FORMAT_Y410:
+			convert_Y410_to_float(cvt);
+			return;
+		case DRM_FORMAT_Y416:
+			convert_yuv16_to_float(cvt, true);
  			return;
  		}
  	} else if (cvt->src.fb->drm_format == IGT_FORMAT_FLOAT) {
@@ -2172,7 +2320,13 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_Y210:
  		case DRM_FORMAT_Y212:
  		case DRM_FORMAT_Y216:
-			convert_float_to_yuv16(cvt);
+			convert_float_to_yuv16(cvt, false);
+			return;
+		case DRM_FORMAT_Y410:
+			convert_float_to_Y410(cvt);
+			return;
+		case DRM_FORMAT_Y416:
+			convert_float_to_yuv16(cvt, true);
  			return;
  		}
  	}

lib/igt_fb.c bool igt_format_is_yuv(uint32_t drm_format) · line 2725

Quoted 8 lines
lib/igt_fb.c +2 -0
@@ -2564,6 +2718,8 @@ bool igt_format_is_yuv(uint32_t drm_format)
  	case DRM_FORMAT_Y210:
  	case DRM_FORMAT_Y212:
  	case DRM_FORMAT_Y216:
+	case DRM_FORMAT_Y410:
+	case DRM_FORMAT_Y416:
  	case DRM_FORMAT_YUYV:
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#11 lore raw

Re: [igt-dev] [PATCH v2 4/4] lib/igt_fb: Add support for Y410/Y416 formats, v2.

In reply to Maarten Lankhorst

Tested V2 Y410/Y416 pixel formats on ICL U h/w. CRC mismatch. Since IGT is written for alpha supported Y410 and Y416. Driver code is written for non-alpha Y4xx pixel format.

Tried with pixel_blend_mode property set to DRM_MODE_BLEND_PIXEL_NONE for Y4xx pixel format (as suggested by Maarten), CRC mismatch is still there.

Need to decide whether to change driver or igt?

Quoted 449 lines · Maarten Lankhorst

Y410 is packed with compressed a channel and only 32 bpp, like 10 bits RGB formats. Y416 is a packed 16 bits per component format.

Changes since v1:
- Rebase on top of upstream YUV changes.

---
  include/drm-uapi/drm_fourcc.h |   3 +
  lib/igt_color_encoding.c      |   2 +
  lib/igt_fb.c                  | 204 ++++++++++++++++++++++++++++++----
  3 files changed, 185 insertions(+), 24 deletions(-)
include/drm-uapi/drm_fourcc.h +3 -0
index ff9ea02766ee..62b4ba023a4d 100644
@@ -157,6 +157,9 @@ extern "C" {
  #define DRM_FORMAT_Y212		fourcc_code('Y', '2', '1', '2')
  #define DRM_FORMAT_Y216		fourcc_code('Y', '2', '1', '6')
 
+#define DRM_FORMAT_Y410		fourcc_code('Y', '4', '1', '0') /* [31:0] A:V:Y:U 2:10:10:10 little endian */
+#define DRM_FORMAT_Y416		fourcc_code('Y', '4', '1', '6') /* [127:0] A:V:Y:U 16:16:16:16 little endian */
+
  /*
   * packed YCbCr420 2x2 tiled formats
   * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile
lib/igt_color_encoding.c +2 -0
index 6f82fcec62e4..bc9575fca1b4 100644
@@ -147,6 +147,8 @@ static const struct color_encoding_format {
  	{ DRM_FORMAT_Y210, 65472.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_Y212, 65520.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  	{ DRM_FORMAT_Y216, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
+	{ DRM_FORMAT_Y410, 1023.f, 64.f, 940.f, 64.f, 512.f, 960.f },
+	{ DRM_FORMAT_Y416, 65535.f, 4096.f, 60160.f, 4096.f, 32768.f, 61440.f },
  };
 
  static const struct color_encoding_format *lookup_fourcc(uint32_t fourcc)
lib/igt_fb.c +180 -24
index cccd6bb98395..b8c82b985fd3 100644
@@ -199,6 +199,16 @@ static const struct format_desc_struct {
  	  .num_planes = 1, .plane_bpp = { 32, },
  	  .hsub = 2, .vsub = 1,
  	},
+	{ .name = "Y410", .depth = -1, .drm_id = DRM_FORMAT_Y410,
+	  .cairo_id = CAIRO_FORMAT_RGBA128F,
+	  .num_planes = 1, .plane_bpp = { 32, },
+	  .hsub = 1, .vsub = 1,
+	},
+	{ .name = "Y416", .depth = -1, .drm_id = DRM_FORMAT_Y416,
+	  .cairo_id = CAIRO_FORMAT_RGBA128F,
+	  .num_planes = 1, .plane_bpp = { 64, },
+	  .hsub = 1, .vsub = 1,
+	},
  	{ .name = "P010", .depth = -1, .drm_id = DRM_FORMAT_P010,
  	  .cairo_id = CAIRO_FORMAT_RGB96F,
  	  .num_planes = 2, .plane_bpp = { 16, 32 },
@@ -584,6 +594,28 @@ static void clear_yuv_buffer(struct igt_fb *fb)
  			fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
  		break;
 
+	case DRM_FORMAT_Y410:
+		wmemset(ptr + fb->offsets[0],
+			full_range ? 0xe0000200 : 0xe0010200,
+		fb->strides[0] * fb->plane_height[0] / sizeof(wchar_t));
+		break;
+	case DRM_FORMAT_Y416: {
+		struct ayuv16 { uint16_t u, y, v, a; };
+		const struct ayuv16 pixel = {
+			.a = 0xffff,
+			.v = full_range ? 0 : 0x1000,
+			.y = 0x8000,
+			.u = full_range ? 0 : 0x1000
+		};
+
+		for (int i = 0; i < fb->plane_height[0]; i++) {
+			struct ayuv16 *cur = ptr + fb->offsets[0] + fb->strides[0] * i;
+
+			for (int j = 0; i < fb->plane_width[0]; j++)
+				*cur++ = pixel;
+		}
+		break;
+		}
  	}
 
  	igt_fb_unmap_buffer(fb, ptr);
@@ -1649,10 +1681,11 @@ static void convert_src_put(const struct fb_convert *cvt,
  }
 
  struct yuv_parameters {
-	unsigned	y_inc;
+	unsigned	ay_inc;
  	unsigned	uv_inc;
-	unsigned	y_stride;
+	unsigned	ay_stride;
  	unsigned	uv_stride;
+	unsigned	a_offset;
  	unsigned	y_offset;
  	unsigned	u_offset;
  	unsigned	v_offset;
@@ -1667,7 +1700,7 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_P010:
  	case DRM_FORMAT_P012:
  	case DRM_FORMAT_P016:
-		params->y_inc = 1;
+		params->ay_inc = 1;
  		params->uv_inc = 2;
  		break;
 
@@ -1678,12 +1711,13 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_Y210:
  	case DRM_FORMAT_Y212:
  	case DRM_FORMAT_Y216:
-		params->y_inc = 2;
+		params->ay_inc = 2;
  		params->uv_inc = 4;
  		break;
 
+	case DRM_FORMAT_Y416:
  	case DRM_FORMAT_XYUV8888:
-		params->y_inc = 4;
+		params->ay_inc = 4;
  		params->uv_inc = 4;
  		break;
  	}
@@ -1693,7 +1727,7 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_P010:
  	case DRM_FORMAT_P012:
  	case DRM_FORMAT_P016:
-		params->y_stride = fb->strides[0];
+		params->ay_stride = fb->strides[0];
  		params->uv_stride = fb->strides[1];
  		break;
 
@@ -1705,7 +1739,8 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  	case DRM_FORMAT_Y212:
  	case DRM_FORMAT_Y216:
  	case DRM_FORMAT_XYUV8888:
-		params->y_stride = fb->strides[0];
+	case DRM_FORMAT_Y416:
+		params->ay_stride = fb->strides[0];
  		params->uv_stride = fb->strides[0];
  		break;
  	}
@@ -1757,6 +1792,13 @@ static void get_yuv_parameters(struct igt_fb *fb, struct yuv_parameters *params)
  		params->v_offset = fb->offsets[0] + 6;
  		break;
 
+	case DRM_FORMAT_Y416:
+		params->a_offset = fb->offsets[0] + 6;
+		params->y_offset = fb->offsets[0] + 2;
+		params->u_offset = fb->offsets[0];
+		params->v_offset = fb->offsets[0] + 4;
+		break;
+
  	case DRM_FORMAT_XYUV8888:
  		params->y_offset = fb->offsets[0] + 1;
  		params->u_offset = fb->offsets[0] + 2;
@@ -1808,7 +1850,7 @@ static void convert_yuv_to_rgb24(struct fb_convert *cvt)
  			write_rgb(rgb_tmp, &rgb);
 
  			rgb_tmp += bpp;
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((src_fmt->hsub == 1) || (j % src_fmt->hsub)) {
  				u_tmp += params.uv_inc;
@@ -1817,7 +1859,7 @@ static void convert_yuv_to_rgb24(struct fb_convert *cvt)
  		}
 
  		rgb24 += rgb24_stride;
-		y += params.y_stride;
+		y += params.ay_stride;
 
  		if ((src_fmt->vsub == 1) || (i % src_fmt->vsub)) {
  			u += params.uv_stride;
@@ -1868,7 +1910,7 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt)
  			rgb_tmp += bpp;
 
  			*y_tmp = yuv.d[0];
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((i % dst_fmt->vsub) || (j % dst_fmt->hsub))
  				continue;
@@ -1905,7 +1947,7 @@ static void convert_rgb24_to_yuv(struct fb_convert *cvt)
  		}
 
  		rgb24 += rgb24_stride;
-		y += params.y_stride;
+		y += params.ay_stride;
 
  		if ((i % dst_fmt->vsub) == (dst_fmt->vsub - 1)) {
  			u += params.uv_stride;
@@ -1929,13 +1971,13 @@ static void write_rgbf(float *rgb24, const struct igt_vec4 *rgb)
  	rgb24[2] = rgb->d[2];
  }
 
-static void convert_yuv16_to_float(struct fb_convert *cvt)
+static void convert_yuv16_to_float(struct fb_convert *cvt, bool alpha)
  {
  	const struct format_desc_struct *src_fmt =
  		lookup_drm_format(cvt->src.fb->drm_format);
  	int i, j;
-	uint8_t fpp = 3;
-	uint16_t *y, *u, *v;
+	uint8_t fpp = alpha ? 4 : 3;
+	uint16_t *a, *y, *u, *v;
  	float *ptr = cvt->dst.ptr;
  	unsigned int float_stride = cvt->dst.fb->strides[0] / sizeof(*ptr);
  	struct igt_mat4 m = igt_ycbcr_to_rgb_matrix(cvt->src.fb->drm_format,
@@ -1954,11 +1996,13 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  		   !(params.u_offset % sizeof(*buf)) &&
  		   !(params.v_offset % sizeof(*buf)));
 
+	a = buf + params.a_offset / sizeof(*buf);
  	y = buf + params.y_offset / sizeof(*buf);
  	u = buf + params.u_offset / sizeof(*buf);
  	v = buf + params.v_offset / sizeof(*buf);
 
  	for (i = 0; i < cvt->dst.fb->height; i++) {
+		const uint16_t *a_tmp = a;
  		const uint16_t *y_tmp = y;
  		const uint16_t *u_tmp = u;
  		const uint16_t *v_tmp = v;
@@ -1975,8 +2019,13 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  			rgb = igt_matrix_transform(&m, &yuv);
  			write_rgbf(rgb_tmp, &rgb);
 
+			if (alpha) {
+				rgb_tmp[3] = ((float)*a_tmp) / 65535.f;
+				a_tmp += params.ay_inc;
+			}
+
  			rgb_tmp += fpp;
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((src_fmt->hsub == 1) || (j % src_fmt->hsub)) {
  				u_tmp += params.uv_inc;
@@ -1985,7 +2034,9 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  		}
 
  		ptr += float_stride;
-		y += params.y_stride / sizeof(*y);
+
+		a += params.ay_stride / sizeof(*a);
+		y += params.ay_stride / sizeof(*y);
 
  		if ((src_fmt->vsub == 1) || (i % src_fmt->vsub)) {
  			u += params.uv_stride / sizeof(*u);
@@ -1996,14 +2047,14 @@ static void convert_yuv16_to_float(struct fb_convert *cvt)
  	convert_src_put(cvt, buf);
  }
 
-static void convert_float_to_yuv16(struct fb_convert *cvt)
+static void convert_float_to_yuv16(struct fb_convert *cvt, bool alpha)
  {
  	const struct format_desc_struct *dst_fmt =
  		lookup_drm_format(cvt->dst.fb->drm_format);
  	int i, j;
-	uint16_t *y, *u, *v;
+	uint16_t *a, *y, *u, *v;
  	const float *ptr = cvt->src.ptr;
-	uint8_t fpp = 3;
+	uint8_t fpp = alpha ? 4 : 3;
  	unsigned float_stride = cvt->src.fb->strides[0] / sizeof(*ptr);
  	struct igt_mat4 m = igt_rgb_to_ycbcr_matrix(cvt->src.fb->drm_format,
  						    cvt->dst.fb->drm_format,
@@ -2015,16 +2066,19 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  		   igt_format_is_yuv(cvt->dst.fb->drm_format));
 
  	get_yuv_parameters(cvt->dst.fb, &params);
-	igt_assert(!(params.y_offset % sizeof(*y)) &&
+	igt_assert(!(params.a_offset % sizeof(*a)) &&
+		   !(params.y_offset % sizeof(*y)) &&
  		   !(params.u_offset % sizeof(*u)) &&
  		   !(params.v_offset % sizeof(*v)));
 
+	a = cvt->dst.ptr + params.a_offset;
  	y = cvt->dst.ptr + params.y_offset;
  	u = cvt->dst.ptr + params.u_offset;
  	v = cvt->dst.ptr + params.v_offset;
 
  	for (i = 0; i < cvt->dst.fb->height; i++) {
  		const float *rgb_tmp = ptr;
+		uint16_t *a_tmp = a;
  		uint16_t *y_tmp = y;
  		uint16_t *u_tmp = u;
  		uint16_t *v_tmp = v;
@@ -2037,10 +2091,15 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  			read_rgbf(&rgb, rgb_tmp);
  			yuv = igt_matrix_transform(&m, &rgb);
 
+			if (alpha) {
+				*a_tmp = rgb_tmp[3] * 65535.f + .5f;
+				a_tmp += params.ay_inc;
+			}
+
  			rgb_tmp += fpp;
 
  			*y_tmp = yuv.d[0];
-			y_tmp += params.y_inc;
+			y_tmp += params.ay_inc;
 
  			if ((i % dst_fmt->vsub) || (j % dst_fmt->hsub))
  				continue;
@@ -2077,7 +2136,8 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  		}
 
  		ptr += float_stride;
-		y += params.y_stride / sizeof(*y);
+		a += params.ay_stride / sizeof(*a);
+		y += params.ay_stride / sizeof(*y);
 
  		if ((i % dst_fmt->vsub) == (dst_fmt->vsub - 1)) {
  			u += params.uv_stride / sizeof(*u);
@@ -2086,6 +2146,88 @@ static void convert_float_to_yuv16(struct fb_convert *cvt)
  	}
  }
 
+static void convert_Y410_to_float(struct fb_convert *cvt)
+{
+	int i, j;
+	const uint32_t *yuyv;
+	uint32_t *buf;
+	float *ptr = cvt->dst.ptr;
+	unsigned int float_stride = cvt->dst.fb->strides[0] / sizeof(*ptr);
+	unsigned int yuyv_stride = cvt->src.fb->strides[0] / sizeof(*yuyv);
+	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);
+
+	igt_assert(cvt->src.fb->drm_format == DRM_FORMAT_Y410 &&
+		   cvt->dst.fb->drm_format == IGT_FORMAT_FLOAT);
+
+	yuyv = buf = convert_src_get(cvt);
+
+	for (i = 0; i < cvt->dst.fb->height; i++) {
+		for (j = 0; j < cvt->dst.fb->width; j++) {
+			/* Convert 2x1 pixel blocks */
+			struct igt_vec4 yuv;
+			struct igt_vec4 rgb;
+
+			yuv.d[0] = yuyv[j] & 0x3ff;
+			yuv.d[1] = (yuyv[j] >> 10) & 0x3ff;
+			yuv.d[2] = (yuyv[j] >> 20) & 0x3ff;
+			yuv.d[3] = 1.f;
+
+			rgb = igt_matrix_transform(&m, &yuv);
+
+			write_rgbf(&ptr[j * 4 + 0], &rgb);
+			ptr[j * 4 + 3] = (float)(yuyv[j] >> 30) / 3;
+		}
+
+		ptr += float_stride;
+		yuyv += yuyv_stride;
+	}
+
+	convert_src_put(cvt, buf);
+}
+
+static void convert_float_to_Y410(struct fb_convert *cvt)
+{
+	int i, j;
+	uint32_t *yuyv = cvt->dst.ptr;
+	const float *ptr = cvt->src.ptr;
+	unsigned float_stride = cvt->src.fb->strides[0] / sizeof(*ptr);
+	unsigned yuyv_stride = cvt->dst.fb->strides[0] / sizeof(*yuyv);
+	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);
+
+	igt_assert(cvt->src.fb->drm_format == IGT_FORMAT_FLOAT &&
+		   cvt->dst.fb->drm_format == DRM_FORMAT_Y410);
+
+	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;
+			uint8_t alpha = ptr[j * 4 + 3] * 3.f + .5f;
+			uint16_t y, cb, cr;
+
+			read_rgbf(&rgb, &ptr[j * 4 + 0]);
+
+			yuv = igt_matrix_transform(&m, &rgb);
+			cr = yuv.d[0];
+			y = yuv.d[1];
+			cb = yuv.d[2];
+
+			yuyv[j] = ((cr & 0x3ff) << 0) |
+				  ((y & 0x3ff) << 10) |
+				  ((cb & 0x3ff) << 20) |
+				  (alpha << 30);
+		}
+
+		ptr += float_stride;
+		yuyv += yuyv_stride;
+	}
+}
+
  static void convert_pixman(struct fb_convert *cvt)
  {
  	pixman_format_code_t src_pixman = drm_format_to_pixman(cvt->src.fb->drm_format);
@@ -2161,7 +2303,13 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_Y210:
  		case DRM_FORMAT_Y212:
  		case DRM_FORMAT_Y216:
-			convert_yuv16_to_float(cvt);
+			convert_yuv16_to_float(cvt, false);
+			return;
+		case DRM_FORMAT_Y410:
+			convert_Y410_to_float(cvt);
+			return;
+		case DRM_FORMAT_Y416:
+			convert_yuv16_to_float(cvt, true);
  			return;
  		}
  	} else if (cvt->src.fb->drm_format == IGT_FORMAT_FLOAT) {
@@ -2172,7 +2320,13 @@ static void fb_convert(struct fb_convert *cvt)
  		case DRM_FORMAT_Y210:
  		case DRM_FORMAT_Y212:
  		case DRM_FORMAT_Y216:
-			convert_float_to_yuv16(cvt);
+			convert_float_to_yuv16(cvt, false);
+			return;
+		case DRM_FORMAT_Y410:
+			convert_float_to_Y410(cvt);
+			return;
+		case DRM_FORMAT_Y416:
+			convert_float_to_yuv16(cvt, true);
  			return;
  		}
  	}
@@ -2564,6 +2718,8 @@ bool igt_format_is_yuv(uint32_t drm_format)
  	case DRM_FORMAT_Y210:
  	case DRM_FORMAT_Y212:
  	case DRM_FORMAT_Y216:
+	case DRM_FORMAT_Y410:
+	case DRM_FORMAT_Y416:
  	case DRM_FORMAT_YUYV:
  	case DRM_FORMAT_YVYU:
  	case DRM_FORMAT_UYVY:
Signature · 1 line
~Swati Sharma

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#12 lore raw

[igt-dev] ✓ Fi.CI.BAT: success for series starting with [v2,1/4] lib/color_encoding: Prepare support for HDR modes.

In reply to Maarten Lankhorst
== Series Details ==

== Series Details ==

Series: series starting with [v2,1/4] lib/color_encoding: Prepare support for HDR modes.
URL : https://patchwork.freedesktop.org/series/56337/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_5557 -> IGTPW_2350
====================================================

Summary
-------

**SUCCESS**

No regressions found.

External URL: https://patchwork.freedesktop.org/api/1.0/series/56337/revisions/1/mbox/

Known issues
------------

Here are the changes found in IGTPW_2350 that come from known issues:

### IGT changes ###

#### Issues hit ####

* igt@kms_frontbuffer_tracking@basic:
- fi-hsw-peppy: NOTRUN -> DMESG-FAIL [fdo#102614]

* igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
- fi-skl-6700k2: PASS -> FAIL [fdo#103375] +3
- fi-byt-clapper: PASS -> FAIL [fdo#103191] / [fdo#107362] +1

* igt@pm_rpm@basic-rte:
- fi-byt-n2820: PASS -> FAIL [fdo#108800]
- fi-byt-j1900: PASS -> FAIL [fdo#108800]

* igt@pm_rpm@module-reload:
- fi-skl-6770hq: NOTRUN -> FAIL [fdo#108511]

#### Possible fixes ####

* igt@kms_busy@basic-flip-b:
- fi-gdg-551: FAIL [fdo#103182] -> PASS

* igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
- fi-blb-e6850: INCOMPLETE [fdo#107718] -> PASS

{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).

[fdo#102614]: https://bugs.freedesktop.org/show_bug.cgi?id=102614
[fdo#103182]: https://bugs.freedesktop.org/show_bug.cgi?id=103182
[fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
[fdo#103375]: https://bugs.freedesktop.org/show_bug.cgi?id=103375
[fdo#107362]: https://bugs.freedesktop.org/show_bug.cgi?id=107362
[fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
[fdo#108511]: https://bugs.freedesktop.org/show_bug.cgi?id=108511
[fdo#108800]: https://bugs.freedesktop.org/show_bug.cgi?id=108800
[fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
[fdo#109527]: https://bugs.freedesktop.org/show_bug.cgi?id=109527

Participating hosts (47 -> 45)
------------------------------

Additional (3): fi-skl-guc fi-skl-6770hq fi-hsw-peppy
Missing (5): fi-kbl-soraka fi-ilk-m540 fi-byt-squawks fi-bsw-cyan fi-bdw-samus

Build changes
-------------

* IGT: IGT_4812 -> IGTPW_2350

CI_DRM_5557: 72302b1c5245655423f75a857aec82f037991b6f @ git://anongit.freedesktop.org/gfx-ci/linux
IGTPW_2350: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2350/
IGT_4812: 592b854fead32c2b0dac7198edfb9a6bffd66932 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2350/
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#13 lore raw

[igt-dev] ✓ Fi.CI.IGT: success for series starting with [v2,1/4] lib/color_encoding: Prepare support for HDR modes.

In reply to Maarten Lankhorst
== Series Details ==

== Series Details ==

Series: series starting with [v2,1/4] lib/color_encoding: Prepare support for HDR modes.
URL : https://patchwork.freedesktop.org/series/56337/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_5557_full -> IGTPW_2350_full
====================================================

Summary
-------

**SUCCESS**

No regressions found.

External URL: https://patchwork.freedesktop.org/api/1.0/series/56337/revisions/1/mbox/

Known issues
------------

Here are the changes found in IGTPW_2350_full that come from known issues:

### IGT changes ###

#### Issues hit ####

* igt@gem_cs_tlb@basic-default:
- shard-snb: PASS -> INCOMPLETE [fdo#105411]

* igt@gem_exec_schedule@pi-ringfull-bsd2:
- shard-kbl: NOTRUN -> FAIL [fdo#103158] +2

* igt@gem_mmap_gtt@hang:
- shard-kbl: NOTRUN -> FAIL [fdo#109469]

* igt@kms_available_modes_crc@available_mode_test_crc:

    - shard-apl:          PASS -> FAIL [fdo#106641]
    - shard-glk:          PASS -> FAIL [fdo#106641]
    - shard-kbl:          NOTRUN -> FAIL [fdo#106641]

* igt@kms_busy@extended-modeset-hang-newfb-render-b:
- shard-kbl: NOTRUN -> DMESG-WARN [fdo#107956] +4

* igt@kms_busy@extended-modeset-hang-newfb-with-reset-render-b:
- shard-snb: NOTRUN -> DMESG-WARN [fdo#107956]

* igt@kms_busy@extended-pageflip-hang-newfb-render-a:
- shard-apl: NOTRUN -> DMESG-WARN [fdo#107956]

* igt@kms_ccs@pipe-b-crc-sprite-planes-basic:
- shard-glk: PASS -> FAIL [fdo#108145]

* igt@kms_color@pipe-b-degamma:
- shard-apl: PASS -> FAIL [fdo#104782] +1

* igt@kms_content_protection@atomic:
- shard-kbl: NOTRUN -> FAIL [fdo#108597] +1

* igt@kms_cursor_crc@cursor-128x128-suspend:
- shard-apl: PASS -> FAIL [fdo#103191] / [fdo#103232] +1

* igt@kms_cursor_crc@cursor-256x256-sliding:
- shard-glk: PASS -> FAIL [fdo#103232]
- shard-kbl: PASS -> FAIL [fdo#103232]

* igt@kms_cursor_crc@cursor-64x21-random:
- shard-apl: PASS -> FAIL [fdo#103232] +5

* igt@kms_cursor_crc@cursor-64x64-dpms:
- shard-kbl: NOTRUN -> FAIL [fdo#103232]

* igt@kms_cursor_crc@cursor-64x64-suspend:
- shard-glk: PASS -> INCOMPLETE [fdo#103359] / [k.org#198133]
- shard-kbl: NOTRUN -> FAIL [fdo#103191] / [fdo#103232]

* igt@kms_flip@flip-vs-expired-vblank:
- shard-apl: PASS -> FAIL [fdo#102887] / [fdo#105363]

* igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-wc:
- shard-glk: PASS -> FAIL [fdo#103167] +4

* igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt:
- shard-apl: PASS -> FAIL [fdo#103167] +4

* igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-render:
- shard-kbl: PASS -> FAIL [fdo#103167]

* igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-fullscreen:
- shard-kbl: NOTRUN -> FAIL [fdo#103167]

* igt@kms_plane_alpha_blend@pipe-a-constant-alpha-max:
- shard-apl: NOTRUN -> FAIL [fdo#108145]

* igt@kms_plane_alpha_blend@pipe-c-alpha-7efc:
- shard-kbl: NOTRUN -> FAIL [fdo#108145] / [fdo#108590] +3

* igt@kms_plane_alpha_blend@pipe-c-alpha-opaque-fb:
- shard-kbl: NOTRUN -> FAIL [fdo#108145] +4

* igt@kms_plane_multiple@atomic-pipe-b-tiling-y:
- shard-glk: PASS -> FAIL [fdo#103166] +3

* igt@kms_plane_multiple@atomic-pipe-c-tiling-yf:
- shard-apl: PASS -> FAIL [fdo#103166] +4
- shard-kbl: PASS -> FAIL [fdo#103166] +1

* igt@kms_rotation_crc@multiplane-rotation-cropping-bottom:
- shard-kbl: PASS -> DMESG-FAIL [fdo#105763]

* igt@kms_rotation_crc@multiplane-rotation-cropping-top:
- shard-kbl: NOTRUN -> FAIL [fdo#109016]

#### Possible fixes ####

* igt@gem_exec_blt@cold-min:
- shard-glk: DMESG-WARN [fdo#105763] / [fdo#106538] -> PASS

* igt@i915_selftest@live_hangcheck:
- shard-snb: INCOMPLETE [fdo#105411] -> PASS +1

* igt@kms_busy@extended-pageflip-hang-newfb-render-b:
- shard-apl: DMESG-WARN [fdo#107956] -> PASS

* igt@kms_busy@extended-pageflip-hang-newfb-render-c:
- shard-glk: DMESG-WARN [fdo#107956] -> PASS

* igt@kms_color@pipe-a-degamma:
- shard-apl: FAIL [fdo#104782] / [fdo#108145] -> PASS

* igt@kms_cursor_crc@cursor-256x85-random:
- shard-apl: FAIL [fdo#103232] -> PASS +4

* igt@kms_cursor_crc@cursor-size-change:
- shard-glk: FAIL [fdo#103232] -> PASS +2

* igt@kms_cursor_legacy@2x-long-nonblocking-modeset-vs-cursor-atomic:
- shard-glk: FAIL [fdo#105454] / [fdo#106509] -> PASS

* igt@kms_flip@basic-plain-flip:
- shard-hsw: DMESG-WARN [fdo#102614] -> PASS

* igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-blt:
- shard-snb: {SKIP} [fdo#109271] -> PASS +5

* igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt:
- shard-glk: FAIL [fdo#103167] -> PASS +1

* igt@kms_plane@pixel-format-pipe-b-planes-source-clamping:
- shard-apl: FAIL [fdo#108948] -> PASS

* igt@kms_plane@plane-position-covered-pipe-b-planes:
- shard-kbl: FAIL [fdo#103166] -> PASS

* igt@kms_plane@plane-position-covered-pipe-c-planes:
- shard-apl: FAIL [fdo#103166] -> PASS +3

* igt@kms_plane_alpha_blend@pipe-c-constant-alpha-max:
- shard-glk: FAIL [fdo#108145] -> PASS

* igt@kms_plane_multiple@atomic-pipe-a-tiling-y:
- shard-glk: FAIL [fdo#103166] -> PASS

* igt@kms_setmode@basic:
- shard-kbl: FAIL [fdo#99912] -> PASS

{name}: This element is suppressed. This means it is ignored when computing
the status of the difference (SUCCESS, WARNING, or FAILURE).

[fdo#102614]: https://bugs.freedesktop.org/show_bug.cgi?id=102614
[fdo#102887]: https://bugs.freedesktop.org/show_bug.cgi?id=102887
[fdo#103158]: https://bugs.freedesktop.org/show_bug.cgi?id=103158
[fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
[fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
[fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
[fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
[fdo#103359]: https://bugs.freedesktop.org/show_bug.cgi?id=103359
[fdo#104782]: https://bugs.freedesktop.org/show_bug.cgi?id=104782
[fdo#105363]: https://bugs.freedesktop.org/show_bug.cgi?id=105363
[fdo#105411]: https://bugs.freedesktop.org/show_bug.cgi?id=105411
[fdo#105454]: https://bugs.freedesktop.org/show_bug.cgi?id=105454
[fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
[fdo#106509]: https://bugs.freedesktop.org/show_bug.cgi?id=106509
[fdo#106538]: https://bugs.freedesktop.org/show_bug.cgi?id=106538
[fdo#106641]: https://bugs.freedesktop.org/show_bug.cgi?id=106641
[fdo#107956]: https://bugs.freedesktop.org/show_bug.cgi?id=107956
[fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
[fdo#108590]: https://bugs.freedesktop.org/show_bug.cgi?id=108590
[fdo#108597]: https://bugs.freedesktop.org/show_bug.cgi?id=108597
[fdo#108948]: https://bugs.freedesktop.org/show_bug.cgi?id=108948
[fdo#109016]: https://bugs.freedesktop.org/show_bug.cgi?id=109016
[fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
[fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
[fdo#109469]: https://bugs.freedesktop.org/show_bug.cgi?id=109469
[fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912
[k.org#198133]: https://bugzilla.kernel.org/show_bug.cgi?id=198133

Participating hosts (7 -> 5)
------------------------------

Missing (2): shard-skl shard-iclb

Build changes
-------------

* IGT: IGT_4812 -> IGTPW_2350
* Piglit: piglit_4509 -> None

CI_DRM_5557: 72302b1c5245655423f75a857aec82f037991b6f @ git://anongit.freedesktop.org/gfx-ci/linux
IGTPW_2350: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2350/
IGT_4812: 592b854fead32c2b0dac7198edfb9a6bffd66932 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2350/
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

Reviewed-by on v2 1/4
#14 lore raw
In reply to Maarten Lankhorst
Quoted 198 lines · Maarten Lankhorst
---
  lib/igt_color_encoding.c | 83 +++++++++++++++++++++++++++++++---------
  lib/igt_color_encoding.h |  9 ++++-
  lib/igt_fb.c             | 10 +++--
  3 files changed, 79 insertions(+), 23 deletions(-)
lib/igt_color_encoding.c +65 -18
index 03e16e0c9658..4cbe18e217e3 100644
@@ -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,105 @@ 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_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);
  }
lib/igt_color_encoding.h +7 -2
index 3884e4939f4c..db45b16d3687 100644
@@ -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__ */
lib/igt_fb.c +4 -2
index 5d8c187a9ac9..db3ae06748d1 100644
@@ -1508,7 +1508,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,
@@ -1681,7 +1681,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 = { };

lib/igt_fb.c static void convert_rgb24_to_yuv(struct fb_convert *cvt) · line 1752

Quoted 10 lines
lib/igt_fb.c +3 -1
@@ -1742,7 +1744,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 = { };
 

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#15 lore raw
In reply to Maarten Lankhorst
Quoted 72 lines · Maarten Lankhorst
---
  lib/igt_color_encoding.c | 83 +++++++++++++++++++++++++++++++---------
  lib/igt_color_encoding.h |  9 ++++-
  lib/igt_fb.c             | 10 +++--
  3 files changed, 79 insertions(+), 23 deletions(-)
lib/igt_color_encoding.c +21 -14
index 03e16e0c9658..4cbe18e217e3 100644
@@ -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,105 @@ 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);

lib/igt_color_encoding.c static struct igt_mat4 ycbcr_to_rgb_matrix(const struct color_encoding *e) · line 132

Quoted 10 lines
lib/igt_color_encoding.c +4 -1
+		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;
+

I think no need of new lines here. Can be removed? :/

Quoted 5 lines
lib/igt_color_encoding.c +5 -0
+	float max_val;
+
+	float ofs_y, max_y, ofs_cbcr, mid_cbcr, max_cbcr;
+} formats[] = {
+	{ DRM_FORMAT_XRGB8888, 255.f, },

lib/igt_color_encoding.c static struct igt_mat4 ycbcr_to_rgb_matrix(const struct color_encoding *e) · line 147

Quoted 10 lines
lib/igt_color_encoding.c +10 -0
+	{ DRM_FORMAT_NV12, 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;

Insert a new line here?

Quoted 110 lines
lib/igt_color_encoding.c +25 -3
+	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);
  }
lib/igt_color_encoding.h +7 -2
index 3884e4939f4c..db45b16d3687 100644
@@ -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__ */
lib/igt_fb.c +7 -3
index 5d8c187a9ac9..db3ae06748d1 100644
@@ -1508,7 +1508,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,
@@ -1681,7 +1681,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 = { };
@@ -1742,7 +1744,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 = { };
 
Signature · 5 lines
~Swati
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#16 lore raw
In reply to Maarten Lankhorst

Should we state which all HDR formats are?

Quoted 207 lines · Maarten Lankhorst
---
  lib/igt_color_encoding.c | 83 +++++++++++++++++++++++++++++++---------
  lib/igt_color_encoding.h |  9 ++++-
  lib/igt_fb.c             | 10 +++--
  3 files changed, 79 insertions(+), 23 deletions(-)
lib/igt_color_encoding.c +65 -18
index 03e16e0c9658..4cbe18e217e3 100644
@@ -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,105 @@ 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_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);
  }
lib/igt_color_encoding.h +7 -2
index 3884e4939f4c..db45b16d3687 100644
@@ -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__ */
lib/igt_fb.c +7 -3
index 5d8c187a9ac9..db3ae06748d1 100644
@@ -1508,7 +1508,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,
@@ -1681,7 +1681,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 = { };
@@ -1742,7 +1744,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 = { };
 
Signature · 1 line
~Swati Sharma

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev