[igt-dev] [PATCH i-g-t v2 7/8] lib: Use igt_matrix for ycbcr<->rgb conversion

Ville Syrjala ville.syrjala at linux.intel.com
Fri Mar 2 08:35:15 UTC 2018


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

Probably horribly inefficient (not that the original code tried to be
particularly efficient), but at least this is now pretty generic so
it'll be super easy to add other color encodings and whatnot.

v2: Rebase

Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 lib/igt_fb.c | 135 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 67 insertions(+), 68 deletions(-)

diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index 5e63637fc610..849675b2be49 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -31,8 +31,10 @@
 
 #include "drmtest.h"
 #include "igt_aux.h"
+#include "igt_color_encoding.h"
 #include "igt_fb.h"
 #include "igt_kms.h"
+#include "igt_matrix.h"
 #include "igt_x86.h"
 #include "ioctl_wrappers.h"
 #include "intel_chipset.h"
@@ -1378,6 +1380,9 @@ static void convert_nv12_to_rgb24(struct igt_fb *fb, struct fb_convert_blit_uplo
 	uint8_t *rgb24 = blit->rgb24.map;
 	unsigned rgb24_stride = blit->rgb24.stride, planar_stride = blit->linear.stride;
 	uint8_t *buf = malloc(blit->linear.size);
+	bool full_range = false; /* FIXME */
+	const struct igt_color_encoding *e = &igt_ycbcr_bt601; /* FIXME */
+	struct igt_mat4 m = igt_ycbcr_to_rgb_matrix(e, full_range);
 
 	/*
 	 * Reading from the BO is awfully slow because of lack of read caching,
@@ -1391,27 +1396,27 @@ static void convert_nv12_to_rgb24(struct igt_fb *fb, struct fb_convert_blit_uplo
 	/* Convert from limited color range BT.601 */
 	for (i = 0; i < fb->height / 2; i++) {
 		for (j = 0; j < fb->width; j++) {
-			float r_, g_, b_, y0, y1, cb, cr;
 			/* Convert 1x2 pixel blocks */
+			struct igt_vec4 yuv0, yuv1;
+			struct igt_vec4 rgb0, rgb1;
 
-			y0 = 1.164f * (y[j] - 16.f);
-			y1 = 1.164f * (y[j + planar_stride] - 16.f);
+			yuv0.d[0] = y[j];
+			yuv1.d[0] = y[j + planar_stride];
+			yuv0.d[1] = yuv1.d[1] = uv[j & ~1];
+			yuv0.d[2] = yuv1.d[2] = uv[j | 1];
+			yuv0.d[3] = yuv1.d[3] = 1.0f;
 
-			cb = uv[j & ~1] - 128.f;
-			cr = uv[j | 1] - 128.f;
+			rgb0 = igt_matrix_transform(&m, &yuv0);
+			rgb1 = igt_matrix_transform(&m, &yuv1);
 
-			r_ =  0.000f * cb +  1.596f * cr;
-			g_ = -0.392f * cb + -0.813f * cr;
-			b_ =  2.017f * cb +  0.000f * cr;
+			rgb24[j * 4 + 2] = clamprgb(rgb0.d[0]);
+			rgb24[j * 4 + 2 + rgb24_stride] = clamprgb(rgb1.d[0]);
 
-			rgb24[j * 4 + 2] = clamprgb(y0 + r_);
-			rgb24[j * 4 + 2 + rgb24_stride] = clamprgb(y1 + r_);
+			rgb24[j * 4 + 1] = clamprgb(rgb0.d[1]);
+			rgb24[j * 4 + 1 + rgb24_stride] = clamprgb(rgb1.d[1]);
 
-			rgb24[j * 4 + 1] = clamprgb(y0 + g_);
-			rgb24[j * 4 + 1 + rgb24_stride] = clamprgb(y1 + g_);
-
-			rgb24[j * 4] = clamprgb(y0 + b_);
-			rgb24[j * 4 + rgb24_stride] = clamprgb(y1 + b_);
+			rgb24[j * 4 + 0] = clamprgb(rgb0.d[2]);
+			rgb24[j * 4 + 0 + rgb24_stride] = clamprgb(rgb1.d[2]);
 		}
 
 		rgb24 += 2 * rgb24_stride;
@@ -1422,20 +1427,20 @@ static void convert_nv12_to_rgb24(struct igt_fb *fb, struct fb_convert_blit_uplo
 	if (fb->height & 1) {
 		/* Convert last row */
 		for (j = 0; j < fb->width; j++) {
-			float r_, g_, b_, y0, cb, cr;
 			/* Convert single pixel */
+			struct igt_vec4 yuv;
+			struct igt_vec4 rgb;
 
-			cb = uv[j & ~1] - 128.f;
-			cr = uv[j | 1] - 128.f;
+			yuv.d[0] = y[j];
+			yuv.d[1] = uv[j & ~1];
+			yuv.d[2] = uv[j | 1];
+			yuv.d[3] = 1.0f;
 
-			y0 = 1.164f * (y[j] - 16.f);
-			r_ =  0.000f * cb +  1.596f * cr;
-			g_ = -0.392f * cb + -0.813f * cr;
-			b_ =  2.017f * cb +  0.000f * cr;
+			rgb = igt_matrix_transform(&m, &yuv);
 
-			rgb24[j * 4 + 2] = clamprgb(y0 + r_);
-			rgb24[j * 4 + 1] = clamprgb(y0 + g_);
-			rgb24[j * 4] = clamprgb(y0 + b_);
+			rgb24[j * 4 + 2] = clamprgb(rgb.d[0]);
+			rgb24[j * 4 + 1] = clamprgb(rgb.d[1]);
+			rgb24[j * 4] = clamprgb(rgb.d[2]);
 		}
 	}
 
@@ -1450,65 +1455,59 @@ static void convert_rgb24_to_nv12(struct igt_fb *fb, struct fb_convert_blit_uplo
 	const uint8_t *rgb24 = blit->rgb24.map;
 	unsigned rgb24_stride = blit->rgb24.stride;
 	unsigned planar_stride = blit->linear.stride;
+	bool full_range = false; /* FIXME */
+	const struct igt_color_encoding *e = &igt_ycbcr_bt601; /* FIXME */
+	struct igt_mat4 m = igt_rgb_to_ycbcr_matrix(e, full_range);
 
 	igt_assert_f(fb->drm_format == DRM_FORMAT_NV12,
 		     "Conversion not implemented for !NV12 planar formats\n");
 
-	for (i = 0; i < fb->plane_height[0]; i++) {
-		/* Use limited color range BT.601 */
+	for (i = 0; i < fb->height / 2; i++) {
+		for (j = 0; j < fb->width; j++) {
+			struct igt_vec4 rgb0, rgb1;
+			struct igt_vec4 yuv0, yuv1;
 
-		for (j = 0; j < fb->plane_width[0]; j++) {
-			float yf = 0.257f * rgb24[j * 4 + 2] +
-				   0.504f * rgb24[j * 4 + 1] +
-				   0.098f * rgb24[j * 4] + 16;
+			rgb0.d[0] = rgb24[j * 4 + 2];
+			rgb0.d[1] = rgb24[j * 4 + 1];
+			rgb0.d[2] = rgb24[j * 4 + 0];
+			rgb0.d[3] = 1.0f;
 
-			y[j] = (uint8_t)yf;
-		}
+			rgb1.d[0] = rgb24[j * 4 + 2 + rgb24_stride];
+			rgb1.d[1] = rgb24[j * 4 + 1 + rgb24_stride];
+			rgb1.d[2] = rgb24[j * 4 + 0 + rgb24_stride];
+			rgb1.d[3] = 1.0f;
 
-		rgb24 += rgb24_stride;
-		y += planar_stride;
-	}
+			yuv0 = igt_matrix_transform(&m, &rgb0);
+			yuv1 = igt_matrix_transform(&m, &rgb1);
 
-	rgb24 = blit->rgb24.map;
+			y[j] = yuv0.d[0];
+			y[j + planar_stride] = yuv1.d[0];
 
-	for (i = 0; i < fb->height / 2; i++) {
-		for (j = 0; j < fb->plane_width[1]; j++) {
-			/*
-			 * Pixel center for Cb'Cr' is between the left top and
-			 * bottom pixel in a 2x2 block, so take the average.
-			 */
-			float uf = -0.148f/2 * rgb24[j * 8 + 2] +
-				   -0.148f/2 * rgb24[j * 8 + 2 + rgb24_stride] +
-				   -0.291f/2 * rgb24[j * 8 + 1] +
-				   -0.291f/2 * rgb24[j * 8 + 1 + rgb24_stride] +
-				    0.439f/2 * rgb24[j * 8] +
-				    0.439f/2 * rgb24[j * 8 + rgb24_stride] + 128;
-			float vf =  0.439f/2 * rgb24[j * 8 + 2] +
-				    0.439f/2 * rgb24[j * 8 + 2 + rgb24_stride] +
-				   -0.368f/2 * rgb24[j * 8 + 1] +
-				   -0.368f/2 * rgb24[j * 8 + 1 + rgb24_stride] +
-				   -0.071f/2 * rgb24[j * 8] +
-				   -0.071f/2 * rgb24[j * 8 + rgb24_stride] + 128;
-			uv[j * 2] = (uint8_t)uf;
-			uv[j * 2 + 1] = (uint8_t)vf;
+			uv[j * 2 + 0] = (yuv0.d[1] + yuv1.d[1]) / 2.0f;
+			uv[j * 2 + 1] = (yuv0.d[2] + yuv1.d[2]) / 2.0f;
 		}
 
 		rgb24 += 2 * rgb24_stride;
+		y += 2 * planar_stride;
 		uv += planar_stride;
 	}
 
 	/* Last row cannot be interpolated between 2 pixels, take the single value */
-	if (i < fb->plane_height[1]) {
-		for (j = 0; j < fb->plane_width[1]; j++) {
-			float uf = -0.148f * rgb24[j * 8 + 2] +
-				   -0.291f * rgb24[j * 8 + 1] +
-				    0.439f * rgb24[j * 8] + 128;
-			float vf =  0.439f * rgb24[j * 8 + 2] +
-				   -0.368f * rgb24[j * 8 + 1] +
-				   -0.071f * rgb24[j * 8] + 128;
-
-			uv[j * 2] = (uint8_t)uf;
-			uv[j * 2 + 1] = (uint8_t)vf;
+	if (fb->height & 1) {
+		for (j = 0; j < fb->width; j++) {
+			struct igt_vec4 rgb;
+			struct igt_vec4 yuv;
+
+			rgb.d[0] = rgb24[j * 4 + 2];
+			rgb.d[1] = rgb24[j * 4 + 1];
+			rgb.d[2] = rgb24[j * 4 + 0];
+			rgb.d[3] = 1.0f;
+
+			yuv = igt_matrix_transform(&m, &rgb);
+
+			y[j] = yuv.d[0];
+			uv[j * 2 + 0] = yuv.d[1];
+			uv[j * 2 + 1] = yuv.d[2];
 		}
 	}
 }
-- 
2.13.6



More information about the igt-dev mailing list