All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH i-g-t 0/4] New pipe level color management tests
@ 2016-01-21 15:11 Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 1/4] lib: kms: add crtc_id to igt_pipe_t Lionel Landwerlin
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-01-21 15:11 UTC (permalink / raw)
  To: intel-gfx

Hi,

This series enables testing pipe level color management using kernel patches
from this serie :

http://lists.freedesktop.org/archives/intel-gfx/2016-January/085922.html

Most of the tests use pipe CRCs to check the results by comparing the output
with the expected output drawn using cairo.

Cheers,

Lionel

Lionel Landwerlin (4):
  lib: kms: add crtc_id to igt_pipe_t
  lib: kms: add helpers for color management properties on pipes
  lib: fb: add igt_paint_color_gradient_range
  tests/kms_color: New test for pipe level color management

 lib/igt_fb.c           |  34 ++
 lib/igt_fb.h           |   3 +
 lib/igt_kms.c          |  75 ++++
 lib/igt_kms.h          |  18 +-
 tests/Makefile.sources |   1 +
 tests/kms_pipe_color.c | 986 +++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1116 insertions(+), 1 deletion(-)
 create mode 100644 tests/kms_pipe_color.c

--
2.6.4
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH i-g-t 1/4] lib: kms: add crtc_id to igt_pipe_t
  2016-01-21 15:11 [PATCH i-g-t 0/4] New pipe level color management tests Lionel Landwerlin
@ 2016-01-21 15:11 ` Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes Lionel Landwerlin
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-01-21 15:11 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_kms.c | 1 +
 lib/igt_kms.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 497118a..f5eef82 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -1004,6 +1004,7 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 		int p = IGT_PLANE_2;
 		int j, type;
 
+		pipe->crtc_id = resources->crtcs[i];
 		pipe->display = display;
 		pipe->pipe = i;
 
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 94f315f..c12c2e1 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -212,6 +212,7 @@ struct igt_pipe {
 	uint64_t background; /* Background color MSB BGR 16bpc LSB */
 	uint32_t background_changed : 1;
 	uint32_t background_property;
+	uint32_t crtc_id;
 };
 
 typedef struct {
-- 
2.6.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes
  2016-01-21 15:11 [PATCH i-g-t 0/4] New pipe level color management tests Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 1/4] lib: kms: add crtc_id to igt_pipe_t Lionel Landwerlin
@ 2016-01-21 15:11 ` Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 3/4] lib: fb: add igt_paint_color_gradient_range Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 4/4] tests/kms_color: New test for pipe level color management Lionel Landwerlin
  3 siblings, 0 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-01-21 15:11 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_kms.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_kms.h | 17 +++++++++++++-
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index f5eef82..984d2ea 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -1136,6 +1136,21 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 						   &prop_value,
 						   NULL);
 				pipe->background = (uint32_t)prop_value;
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "DEGAMMA_LUT",
+						  &pipe->degamma_property,
+						  NULL,
+					  NULL);
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "CTM_MATRIX",
+						  &pipe->ctm_property,
+						  NULL,
+						  NULL);
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "GAMMA_LUT",
+						  &pipe->gamma_property,
+						  NULL,
+						  NULL);
 			}
 		}
 	}
@@ -1285,6 +1300,16 @@ static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, enum igt_plane plane)
 	return &pipe->planes[idx];
 }
 
+bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
+			   uint32_t *prop_id, uint64_t *value,
+			   drmModePropertyPtr *prop)
+{
+	return get_crtc_property(pipe->display->drm_fd,
+				 pipe->crtc_id,
+				 name,
+				 prop_id, value, prop);
+}
+
 static uint32_t igt_plane_get_fb_id(igt_plane_t *plane)
 {
 	if (plane->fb)
@@ -1592,6 +1617,17 @@ static int igt_output_commit(igt_output_t *output,
 		pipe->background_changed = false;
 	}
 
+	if (pipe->color_mgmt_changed) {
+		igt_crtc_set_property(output, pipe->degamma_property,
+				      pipe->degamma_blob);
+		igt_crtc_set_property(output, pipe->ctm_property,
+				      pipe->ctm_blob);
+		igt_crtc_set_property(output, pipe->gamma_property,
+				      pipe->gamma_blob);
+
+		pipe->color_mgmt_changed = false;
+	}
+
 	for (i = 0; i < pipe->n_planes; i++) {
 		igt_plane_t *plane = &pipe->planes[i];
 
@@ -1924,6 +1960,44 @@ void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation)
 	plane->rotation_changed = true;
 }
 
+static void
+igt_pipe_replace_blob(igt_pipe_t *pipe, uint64_t *blob, void *ptr, size_t length)
+{
+	igt_display_t *display = pipe->display;
+	uint32_t blob_id = 0;
+
+	if (*blob != 0)
+		igt_assert(drmModeDestroyPropertyBlob(display->drm_fd,
+						      *blob) == 0);
+
+	if (length > 0)
+		igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
+						     ptr, length, &blob_id) == 0);
+
+	*blob = blob_id;
+}
+
+void
+igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->degamma_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
+void
+igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->ctm_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
+void
+igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->gamma_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
 /**
  * igt_crtc_set_background:
  * @pipe: pipe pointer to which background color to be set
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index c12c2e1..dc87981 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -212,6 +212,15 @@ struct igt_pipe {
 	uint64_t background; /* Background color MSB BGR 16bpc LSB */
 	uint32_t background_changed : 1;
 	uint32_t background_property;
+
+	uint64_t degamma_blob;
+	uint32_t degamma_property;
+	uint64_t ctm_blob;
+	uint32_t ctm_property;
+	uint64_t gamma_blob;
+	uint32_t gamma_property;
+	uint32_t color_mgmt_changed : 1;
+
 	uint32_t crtc_id;
 };
 
@@ -250,12 +259,19 @@ drmModeModeInfo *igt_output_get_mode(igt_output_t *output);
 void igt_output_override_mode(igt_output_t *output, drmModeModeInfo *mode);
 void igt_output_set_pipe(igt_output_t *output, enum pipe pipe);
 igt_plane_t *igt_output_get_plane(igt_output_t *output, enum igt_plane plane);
+bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
+			   uint32_t *prop_id, uint64_t *value,
+			   drmModePropertyPtr *prop);
 
 static inline bool igt_plane_supports_rotation(igt_plane_t *plane)
 {
 	return plane->rotation_property != 0;
 }
 
+void igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length);
+void igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length);
+void igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length);
+
 void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb);
 void igt_plane_set_position(igt_plane_t *plane, int x, int y);
 void igt_plane_set_size(igt_plane_t *plane, int w, int h);
@@ -291,4 +307,3 @@ const unsigned char* igt_kms_get_alt_edid(void);
 
 
 #endif /* __IGT_KMS_H__ */
-
-- 
2.6.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH i-g-t 3/4] lib: fb: add igt_paint_color_gradient_range
  2016-01-21 15:11 [PATCH i-g-t 0/4] New pipe level color management tests Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 1/4] lib: kms: add crtc_id to igt_pipe_t Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes Lionel Landwerlin
@ 2016-01-21 15:11 ` Lionel Landwerlin
  2016-01-21 15:11 ` [PATCH i-g-t 4/4] tests/kms_color: New test for pipe level color management Lionel Landwerlin
  3 siblings, 0 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-01-21 15:11 UTC (permalink / raw)
  To: intel-gfx

This is a helper to draw a gradient between 2 colors.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_fb.c | 34 ++++++++++++++++++++++++++++++++++
 lib/igt_fb.h |  3 +++
 2 files changed, 37 insertions(+)

diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index c985824..2d5cf7a 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -200,6 +200,40 @@ igt_paint_color_gradient(cairo_t *cr, int x, int y, int w, int h,
 	cairo_pattern_destroy(pat);
 }
 
+/**
+ * igt_paint_color_gradient_range:
+ * @cr: cairo drawing context
+ * @x: pixel x-coordination of the fill rectangle
+ * @y: pixel y-coordination of the fill rectangle
+ * @w: width of the fill rectangle
+ * @h: height of the fill rectangle
+ * @sr: red value to use as start gradient color
+ * @sg: green value to use as start gradient color
+ * @sb: blue value to use as start gradient color
+ * @er: red value to use as end gradient color
+ * @eg: green value to use as end gradient color
+ * @eb: blue value to use as end gradient color
+ *
+ * This functions draws a gradient into the rectangle which fades in
+ * from one color to the other using the drawing context @cr.
+ */
+void
+igt_paint_color_gradient_range(cairo_t *cr, int x, int y, int w, int h,
+			       double sr, double sg, double sb,
+			       double er, double eg, double eb)
+{
+	cairo_pattern_t *pat;
+
+	pat = cairo_pattern_create_linear(x, y, x + w, y + h);
+	cairo_pattern_add_color_stop_rgba(pat, 1, sr, sg, sb, 1);
+	cairo_pattern_add_color_stop_rgba(pat, 0, er, eg, eb, 1);
+
+	cairo_rectangle(cr, x, y, w, h);
+	cairo_set_source(cr, pat);
+	cairo_fill(cr);
+	cairo_pattern_destroy(pat);
+}
+
 static void
 paint_test_patterns(cairo_t *cr, int width, int height)
 {
diff --git a/lib/igt_fb.h b/lib/igt_fb.h
index 5cc8644..ee52c73 100644
--- a/lib/igt_fb.h
+++ b/lib/igt_fb.h
@@ -103,6 +103,9 @@ void igt_paint_color_alpha(cairo_t *cr, int x, int y, int w, int h,
 			       double r, double g, double b, double a);
 void igt_paint_color_gradient(cairo_t *cr, int x, int y, int w, int h,
 				  int r, int g, int b);
+void igt_paint_color_gradient_range(cairo_t *cr, int x, int y, int w, int h,
+				    double sr, double sg, double sb,
+				    double er, double eg, double eb);
 void igt_paint_test_pattern(cairo_t *cr, int width, int height);
 void igt_paint_image(cairo_t *cr, const char *filename,
 			 int dst_x, int dst_y, int dst_width, int dst_height);
-- 
2.6.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH i-g-t 4/4] tests/kms_color: New test for pipe level color management
  2016-01-21 15:11 [PATCH i-g-t 0/4] New pipe level color management tests Lionel Landwerlin
                   ` (2 preceding siblings ...)
  2016-01-21 15:11 ` [PATCH i-g-t 3/4] lib: fb: add igt_paint_color_gradient_range Lionel Landwerlin
@ 2016-01-21 15:11 ` Lionel Landwerlin
  3 siblings, 0 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-01-21 15:11 UTC (permalink / raw)
  To: intel-gfx

This test enables testing of :

     * degamma LUTs
     * csc matrix
     * gamma LUTs
     * legacy gamma LUTs

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 tests/Makefile.sources |   1 +
 tests/kms_pipe_color.c | 986 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 987 insertions(+)
 create mode 100644 tests/kms_pipe_color.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 3b2ae99..70d309e 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -81,6 +81,7 @@ TESTS_progs_M = \
 	kms_legacy_colorkey \
 	kms_mmio_vs_cs_flip \
 	kms_pipe_b_c_ivb \
+	kms_pipe_color \
 	kms_pipe_crc_basic \
 	kms_plane \
 	kms_psr_sink_crc \
diff --git a/tests/kms_pipe_color.c b/tests/kms_pipe_color.c
new file mode 100644
index 0000000..e540221
--- /dev/null
+++ b/tests/kms_pipe_color.c
@@ -0,0 +1,986 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <math.h>
+#include <unistd.h>
+
+#include "drm.h"
+#include "drmtest.h"
+#include "igt_core.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+
+
+IGT_TEST_DESCRIPTION("Test Color Features at Pipe level");
+
+/* Data structures for gamma/degamma ramps & ctm matrix. */
+struct _drm_color_ctm {
+	/* Transformation matrix in S31.32 format. */
+	__s64 matrix[9];
+};
+
+struct _drm_color_lut {
+	/*
+	 * Data is U0.16 fixed point format.
+	 */
+	__u16 red;
+	__u16 green;
+	__u16 blue;
+	__u16 reserved;
+};
+
+/* Internal */
+typedef struct {
+	float r, g, b;
+} color_t;
+
+typedef struct {
+	int drm_fd;
+	igt_display_t display;
+	igt_pipe_crc_t *pipe_crc;
+
+	uint32_t color_depth;
+	uint64_t degamma_lut_size;
+	uint64_t gamma_lut_size;
+} data_t;
+
+
+static void paint_gradient_rectangles(data_t *data,
+				      drmModeModeInfo *mode,
+				      color_t *colors,
+				      struct igt_fb *fb)
+{
+	cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, fb);
+	int i, l = mode->hdisplay / 3;
+
+	/* Paint 3 gradient rectangles with red/green/blue between 1.0 and
+	 * 0.5. We want to avoid 0 so each max LUTs only affect their own
+	 * rectangle.
+	 */
+	for (i = 0 ; i < 3; i++) {
+		igt_paint_color_gradient_range(cr, i * l, 0, l, mode->vdisplay,
+					       colors[i].r != 0 ? 0.1 : 0,
+					       colors[i].g != 0 ? 0.1 : 0,
+					       colors[i].b != 0 ? 0.1 : 0,
+					       colors[i].r * 255,
+					       colors[i].g * 255,
+					       colors[i].b * 255);
+	}
+
+	cairo_destroy(cr);
+}
+
+static void paint_rectangles(data_t *data,
+			     drmModeModeInfo *mode,
+			     color_t *colors,
+			     struct igt_fb *fb)
+{
+	cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, fb);
+	int i, l = mode->hdisplay / 3;
+
+	/* Paint 3 solid rectangles. */
+	for (i = 0 ; i < 3; i++) {
+		igt_paint_color(cr, i * l, 0, l, mode->vdisplay,
+				colors[i].r, colors[i].g, colors[i].b);
+	}
+
+	cairo_destroy(cr);
+}
+
+static float *generate_table(uint32_t lut_size, float exp)
+{
+	float *coeffs = malloc(sizeof(float) * lut_size);
+	uint32_t i;
+
+	for (i = 0; i < lut_size; i++)
+		coeffs[i] = powf((float) i * 1.0 / (float) (lut_size - 1), exp);
+
+	return coeffs;
+}
+
+static float *generate_table_max(uint32_t lut_size)
+{
+	float *coeffs = malloc(sizeof(float) * lut_size);
+	uint32_t i;
+
+	coeffs[0] = 0.0;
+	for (i = 1; i < lut_size; i++)
+		coeffs[i] = 1.0;
+
+	return coeffs;
+}
+
+static struct _drm_color_lut *coeffs_to_lut(const float *coefficients,
+					    uint32_t lut_size,
+					    uint32_t color_depth)
+{
+	struct _drm_color_lut *lut;
+	uint32_t i;
+	uint32_t max_value = (1 << 16) - 1;
+	uint32_t mask = ((1 << color_depth) - 1) << 8;
+
+	lut = malloc(sizeof(struct _drm_color_lut) * lut_size);
+
+	for (i = 0; i < lut_size; i++) {
+		uint32_t v = (coefficients[i] * max_value);
+
+		/*
+		 * Hardware might encode colors on a different number of bits
+		 * than what is in our framebuffer (10 or 12bits for example).
+		 * Mask the lower bits not provided by the framebuffer so we
+		 * can do CRC comparisons.
+		 */
+		v &= mask;
+
+		lut[i].red = v;
+		lut[i].green = v;
+		lut[i].blue = v;
+	}
+
+	return lut;
+}
+
+static void set_degamma(igt_pipe_t *pipe,
+			const float *coefficients,
+			uint32_t lut_size,
+			uint32_t color_depth)
+{
+	size_t size = sizeof(struct _drm_color_lut) * lut_size;
+	struct _drm_color_lut *lut = coeffs_to_lut(coefficients,
+						   lut_size,
+						   color_depth);
+
+	igt_pipe_set_degamma_lut(pipe, lut, size);
+
+	free(lut);
+}
+
+static void set_gamma(igt_pipe_t *pipe,
+		      const float *coefficients,
+		      uint32_t lut_size,
+		      uint32_t color_depth)
+{
+	size_t size = sizeof(struct _drm_color_lut) * lut_size;
+	struct _drm_color_lut *lut = coeffs_to_lut(coefficients,
+						   lut_size,
+						   color_depth);
+
+	igt_pipe_set_gamma_lut(pipe, lut, size);
+
+	free(lut);
+}
+
+static void set_ctm(igt_pipe_t *pipe, const float *coefficients)
+{
+	struct _drm_color_ctm ctm;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ctm.matrix); i++) {
+		if (coefficients[i] < 0) {
+			ctm.matrix[i] =
+				(int64_t) (-coefficients[i] * ((int64_t) 1L << 32));
+			ctm.matrix[i] |= 1ULL << 63;
+		} else
+			ctm.matrix[i] =
+				(int64_t) (coefficients[i] * ((int64_t) 1L << 32));
+	}
+
+	igt_pipe_set_ctm_matrix(pipe, &ctm, sizeof(ctm));
+}
+
+#define disable_degamma(pipe) igt_pipe_set_degamma_lut(pipe, NULL, 0)
+#define disable_gamma(pipe) igt_pipe_set_gamma_lut(pipe, NULL, 0)
+#define disable_ctm(pipe) igt_pipe_set_ctm_matrix(pipe, NULL, 0)
+
+static void output_set_property_enum(igt_output_t *output,
+				     const char *property,
+				     const char *enum_value)
+{
+	int i;
+	int32_t value = -1;
+	uint32_t prop_id;
+	drmModePropertyPtr prop;
+
+	igt_require(kmstest_get_property(output->display->drm_fd,
+					 output->id,
+					 DRM_MODE_OBJECT_CONNECTOR,
+					 property,
+					 &prop_id, NULL, &prop));
+
+	igt_assert(prop->flags & DRM_MODE_PROP_ENUM);
+
+	for (i = 0; i < prop->count_enums; i++) {
+		if (!strcmp(prop->enums[i].name, enum_value)) {
+			value = prop->enums[i].value;
+			break;
+		}
+	}
+	igt_assert_neq(value, -1);
+
+	igt_assert_eq(drmModeObjectSetProperty(output->display->drm_fd,
+					       output->id,
+					       DRM_MODE_OBJECT_CONNECTOR,
+					       prop_id, value), 0);
+
+
+	drmModeFreeProperty(prop);
+}
+
+/*
+ * Draw 3 gradient rectangles in red, green and blue, with a maxed out
+ * degamma LUT and verify we have the same CRC as drawing solid color
+ * rectangles with linear degamma LUT.
+ */
+static void test_pipe_degamma(data_t *data,
+			      igt_plane_t *primary)
+{
+	igt_output_t *output;
+	float *degamma_linear, *degamma_full;
+	float *gamma_linear;
+	color_t red_green_blue[] = {
+		{ 1.0, 0.0, 0.0 },
+		{ 0.0, 1.0, 0.0 },
+		{ 0.0, 0.0, 1.0 }
+	};
+
+	degamma_linear = generate_table(data->degamma_lut_size, 1.0);
+	degamma_full = generate_table_max(data->degamma_lut_size);
+
+	gamma_linear = generate_table(data->gamma_lut_size, 1.0);
+
+	for_each_connected_output(&data->display, output) {
+		drmModeModeInfo *mode;
+		struct igt_fb fb_modeset, fb;
+		igt_crc_t crc_fullgamma, crc_fullcolors;
+		int fb_id, fb_modeset_id;
+
+		mode = igt_output_get_mode(output);
+
+		/* Create a framebuffer at the size of the output. */
+		fb_id = igt_create_fb(data->drm_fd,
+				      mode->hdisplay,
+				      mode->hdisplay,
+				      DRM_FORMAT_XRGB8888,
+				      LOCAL_DRM_FORMAT_MOD_NONE,
+				      &fb);
+		igt_assert(fb_id);
+
+		fb_modeset_id = igt_create_fb(data->drm_fd,
+					      mode->hdisplay,
+					      mode->hdisplay,
+					      DRM_FORMAT_XRGB8888,
+					      LOCAL_DRM_FORMAT_MOD_NONE,
+					      &fb_modeset);
+		igt_assert(fb_modeset_id);
+
+		igt_plane_set_fb(primary, &fb_modeset);
+		disable_ctm(primary->pipe);
+		disable_gamma(primary->pipe);
+		disable_degamma(primary->pipe);
+		igt_display_commit(&data->display);
+
+		/* Draw solid colors with no degamma transformation. */
+		paint_rectangles(data, mode, red_green_blue, &fb);
+		igt_plane_set_fb(primary, &fb);
+		set_degamma(primary->pipe, degamma_linear,
+			    data->degamma_lut_size, data->color_depth);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_fullcolors);
+
+		/* Draw a gradient with degamma LUT to remap all
+		 * values to max red/green/blue.
+		 */
+		paint_gradient_rectangles(data, mode, red_green_blue, &fb);
+		igt_plane_set_fb(primary, &fb);
+		set_degamma(primary->pipe, degamma_full,
+			    data->degamma_lut_size, data->color_depth);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_fullgamma);
+
+		/* Verify that the CRC of the software computed output is
+		 * equal to the CRC of the degamma LUT transformation output.
+		 */
+		igt_assert_crc_equal(&crc_fullgamma, &crc_fullcolors);
+	}
+
+	free(degamma_linear);
+	free(degamma_full);
+	free(gamma_linear);
+}
+
+/*
+ * Draw 3 gradient rectangles in red, green and blue, with a maxed out gamma
+ * LUT and verify we have the same CRC as drawing solid color rectangles with
+ * linear gamma LUT.
+ */
+static void test_pipe_gamma(data_t *data,
+			    igt_plane_t *primary)
+{
+	igt_output_t *output;
+	float *degamma_linear;
+	float *gamma_linear, *gamma_full;
+	color_t red_green_blue[] = {
+		{ 1.0, 0.0, 0.0 },
+		{ 0.0, 1.0, 0.0 },
+		{ 0.0, 0.0, 1.0 }
+	};
+
+	degamma_linear = generate_table(data->degamma_lut_size, 1.0);
+
+	gamma_linear = generate_table(data->gamma_lut_size, 1.0);
+	gamma_full = generate_table_max(data->gamma_lut_size);
+
+	for_each_connected_output(&data->display, output) {
+		drmModeModeInfo *mode;
+		struct igt_fb fb_modeset, fb;
+		igt_crc_t crc_fullgamma, crc_fullcolors;
+		int fb_id, fb_modeset_id;
+
+		mode = igt_output_get_mode(output);
+
+		/* Create a framebuffer at the size of the output. */
+		fb_id = igt_create_fb(data->drm_fd,
+				      mode->hdisplay,
+				      mode->hdisplay,
+				      DRM_FORMAT_XRGB8888,
+				      LOCAL_DRM_FORMAT_MOD_NONE,
+				      &fb);
+		igt_assert(fb_id);
+
+		fb_modeset_id = igt_create_fb(data->drm_fd,
+					      mode->hdisplay,
+					      mode->hdisplay,
+					      DRM_FORMAT_XRGB8888,
+					      LOCAL_DRM_FORMAT_MOD_NONE,
+					      &fb_modeset);
+		igt_assert(fb_modeset_id);
+
+		igt_plane_set_fb(primary, &fb_modeset);
+		disable_ctm(primary->pipe);
+		disable_degamma(primary->pipe);
+		disable_gamma(primary->pipe);
+		igt_display_commit(&data->display);
+
+		/* Draw solid colors with no gamma transformation. */
+		paint_rectangles(data, mode, red_green_blue, &fb);
+		igt_plane_set_fb(primary, &fb);
+		set_gamma(primary->pipe, gamma_linear,
+			  data->gamma_lut_size, data->color_depth);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_fullcolors);
+
+		/* Draw a gradient with gamma LUT to remap all values
+		 * to max red/green/blue.
+		 */
+		paint_gradient_rectangles(data, mode, red_green_blue, &fb);
+		igt_plane_set_fb(primary, &fb);
+		set_gamma(primary->pipe, gamma_full,
+			  data->gamma_lut_size, data->color_depth);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_fullgamma);
+
+		/* Verify that the CRC of the software computed output is
+		 * equal to the CRC of the gamma LUT transformation output.
+		 */
+		igt_assert_crc_equal(&crc_fullgamma, &crc_fullcolors);
+	}
+
+	free(degamma_linear);
+	free(gamma_full);
+	free(gamma_linear);
+}
+
+/*
+ * Draw 3 gradient rectangles in red, green and blue, with a maxed out legacy
+ * gamma LUT and verify we have the same CRC as drawing solid color rectangles
+ * with linear legacy gamma LUT.
+ */
+static void test_pipe_legacy_gamma(data_t *data,
+				   igt_plane_t *primary)
+{
+	igt_output_t *output;
+	color_t red_green_blue[] = {
+		{ 1.0, 0.0, 0.0 },
+		{ 0.0, 1.0, 0.0 },
+		{ 0.0, 0.0, 1.0 }
+	};
+	drmModeCrtc *kms_crtc;
+	uint32_t i, legacy_lut_size;
+	uint16_t *red_lut, *green_lut, *blue_lut;
+
+	kms_crtc = drmModeGetCrtc (data->drm_fd, primary->pipe->crtc_id);
+	legacy_lut_size = kms_crtc->gamma_size;
+	drmModeFreeCrtc (kms_crtc);
+
+	red_lut = malloc(sizeof(uint16_t) * legacy_lut_size);
+	green_lut = malloc(sizeof(uint16_t) * legacy_lut_size);
+	blue_lut = malloc(sizeof(uint16_t) * legacy_lut_size);
+
+	red_lut[0] = green_lut[0] = blue_lut[0] = 0;
+	for (i = 1; i < legacy_lut_size; i++)
+		red_lut[i] = green_lut[i] = blue_lut[i] = 0xffff;
+
+	for_each_connected_output(&data->display, output) {
+		drmModeModeInfo *mode;
+		struct igt_fb fb_modeset, fb;
+		igt_crc_t crc_fullgamma, crc_fullcolors;
+		int fb_id, fb_modeset_id;
+
+		mode = igt_output_get_mode(output);
+
+		/* Create a framebuffer at the size of the output. */
+		fb_id = igt_create_fb(data->drm_fd,
+				      mode->hdisplay,
+				      mode->hdisplay,
+				      DRM_FORMAT_XRGB8888,
+				      LOCAL_DRM_FORMAT_MOD_NONE,
+				      &fb);
+		igt_assert(fb_id);
+
+		fb_modeset_id = igt_create_fb(data->drm_fd,
+					      mode->hdisplay,
+					      mode->hdisplay,
+					      DRM_FORMAT_XRGB8888,
+					      LOCAL_DRM_FORMAT_MOD_NONE,
+					      &fb_modeset);
+		igt_assert(fb_modeset_id);
+
+		igt_plane_set_fb(primary, &fb_modeset);
+		disable_degamma(primary->pipe);
+		disable_gamma(primary->pipe);
+		disable_ctm(primary->pipe);
+		igt_display_commit(&data->display);
+
+		/* Draw solid colors with no gamma transformation. */
+		paint_rectangles(data, mode, red_green_blue, &fb);
+		igt_plane_set_fb(primary, &fb);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_fullcolors);
+
+		/* Draw a gradient with gamma LUT to remap all values
+		 * to max red/green/blue.
+		 */
+		paint_gradient_rectangles(data, mode, red_green_blue, &fb);
+		igt_plane_set_fb(primary, &fb);
+		igt_assert_eq(drmModeCrtcSetGamma(data->drm_fd, primary->pipe->crtc_id,
+						  legacy_lut_size, red_lut, green_lut, blue_lut), 0);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_fullgamma);
+
+		/* Verify that the CRC of the software computed output is
+		 * equal to the CRC of the gamma LUT transformation output.
+		 */
+		igt_assert_crc_equal(&crc_fullgamma, &crc_fullcolors);
+
+		/* Reset output. */
+		for (i = 1; i < legacy_lut_size; i++)
+			red_lut[i] = green_lut[i] = blue_lut[i] = i << 8;
+
+		igt_assert_eq(drmModeCrtcSetGamma(data->drm_fd, primary->pipe->crtc_id,
+						  legacy_lut_size, red_lut, green_lut, blue_lut), 0);
+		igt_display_commit(&data->display);
+	}
+
+	free(red_lut);
+	free(green_lut);
+	free(blue_lut);
+}
+
+/*
+ * Draw 3 rectangles using before colors with the ctm matrix apply and verify
+ * the CRC is equal to using after colors with an identify ctm matrix.
+ */
+static void test_pipe_ctm(data_t *data,
+			  igt_plane_t *primary,
+			  color_t *before,
+			  color_t *after,
+			  float *ctm_matrix)
+{
+	const float ctm_identity[] = {
+		1.0, 0.0, 0.0,
+		0.0, 1.0, 0.0,
+		0.0, 0.0, 1.0
+	};
+	float *degamma_linear, *gamma_linear;
+	igt_output_t *output;
+
+	degamma_linear = generate_table(data->degamma_lut_size, 1.0);
+	gamma_linear = generate_table(data->gamma_lut_size, 1.0);
+
+	for_each_connected_output(&data->display, output) {
+		drmModeModeInfo *mode;
+		struct igt_fb fb_modeset, fb;
+		igt_crc_t crc_software, crc_hardware;
+		int fb_id, fb_modeset_id;
+
+		mode = igt_output_get_mode(output);
+
+		/* Create a framebuffer at the size of the output. */
+		fb_id = igt_create_fb(data->drm_fd,
+				      mode->hdisplay,
+				      mode->hdisplay,
+				      DRM_FORMAT_XRGB8888,
+				      LOCAL_DRM_FORMAT_MOD_NONE,
+				      &fb);
+		igt_assert(fb_id);
+
+		fb_modeset_id = igt_create_fb(data->drm_fd,
+					      mode->hdisplay,
+					      mode->hdisplay,
+					      DRM_FORMAT_XRGB8888,
+					      LOCAL_DRM_FORMAT_MOD_NONE,
+					      &fb_modeset);
+		igt_assert(fb_modeset_id);
+		igt_plane_set_fb(primary, &fb_modeset);
+
+		set_degamma(primary->pipe, degamma_linear, data->degamma_lut_size, data->color_depth);
+		set_gamma(primary->pipe, gamma_linear, data->gamma_lut_size, data->color_depth);
+		disable_ctm(primary->pipe);
+		igt_display_commit(&data->display);
+
+		/* No CTM transformation. */
+		paint_rectangles(data, mode, after, &fb);
+		igt_plane_set_fb(primary, &fb);
+		set_ctm(primary->pipe, ctm_identity);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_software);
+
+		/* With CTM transformation. */
+		paint_rectangles(data, mode, before, &fb);
+		igt_plane_set_fb(primary, &fb);
+		set_ctm(primary->pipe, ctm_matrix);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_hardware);
+
+		/* Verify that the CRC of the software computed output is
+		 * equal to the CRC of the CTM matrix transformation output.
+		 */
+		igt_assert_crc_equal(&crc_software, &crc_hardware);
+	}
+
+	free(degamma_linear);
+	free(gamma_linear);
+}
+
+/*
+ * Hardware computes CRC based on the number of bits it is working with (8,
+ * 10, 12, 16 bits), meaning with a framebuffer of 8bits per color will
+ * usually leave the remaining lower bits at 0.
+ *
+ * We're programming the gamma LUT in order to get rid of those lower bits so
+ * we can compare the CRC of a framebuffer without any transformation to a CRC
+ * with transformation applied and verify the CRCs match.
+ *
+ * This test is currently disabled as the CRC computed on Intel hardware seems
+ * to include data on the lower bits, this is preventing us to CRC checks.
+ */
+#if 0
+static void test_pipe_limited_range_ctm(data_t *data,
+					igt_plane_t *primary)
+{
+	float limited_result = 235.0 / 255.0;
+	color_t red_green_blue_limited[] = {
+		{ limited_result, 0.0, 0.0 },
+		{ 0.0, limited_result, 0.0 },
+		{ 0.0, 0.0, limited_result }
+	};
+	color_t red_green_blue_full[] = {
+		{ 0.5, 0.0, 0.0 },
+		{ 0.0, 0.5, 0.0 },
+		{ 0.0, 0.0, 0.5 }
+	};
+	float ctm[] = { 1.0, 0.0, 0.0,
+			0.0, 1.0, 0.0,
+			0.0, 0.0, 1.0 };
+	float *degamma_linear, *gamma_linear;
+	igt_output_t *output;
+
+	degamma_linear = generate_table(data->degamma_lut_size, 1.0);
+	gamma_linear = generate_table(data->gamma_lut_size, 1.0);
+
+	for_each_connected_output(&data->display, output) {
+		drmModeModeInfo *mode;
+		struct igt_fb fb_modeset, fb;
+		igt_crc_t crc_full, crc_limited;
+		int fb_id, fb_modeset_id;
+
+		mode = igt_output_get_mode(output);
+
+		/* Create a framebuffer at the size of the output. */
+		fb_id = igt_create_fb(data->drm_fd,
+				      mode->hdisplay,
+				      mode->hdisplay,
+				      DRM_FORMAT_XRGB8888,
+				      LOCAL_DRM_FORMAT_MOD_NONE,
+				      &fb);
+		igt_assert(fb_id);
+
+		fb_modeset_id = igt_create_fb(data->drm_fd,
+					      mode->hdisplay,
+					      mode->hdisplay,
+					      DRM_FORMAT_XRGB8888,
+					      LOCAL_DRM_FORMAT_MOD_NONE,
+					      &fb_modeset);
+		igt_assert(fb_modeset_id);
+		igt_plane_set_fb(primary, &fb_modeset);
+
+		set_degamma(primary->pipe, degamma_linear,
+			    data->degamma_lut_size, data->color_depth);
+		set_gamma(primary->pipe, gamma_linear,
+			  data->gamma_lut_size, data->color_depth);
+		set_ctm(primary->pipe, ctm);
+
+		output_set_property_enum(output, "Broadcast RGB", "Full");
+		paint_rectangles(data, mode, red_green_blue_limited, &fb);
+		igt_plane_set_fb(primary, &fb);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_full);
+
+		/* Set the output into limited range. */
+		output_set_property_enum(output, "Broadcast RGB", "Limited 16:235");
+		paint_rectangles(data, mode, red_green_blue_full, &fb);
+		igt_plane_set_fb(primary, &fb);
+		igt_display_commit(&data->display);
+		igt_wait_for_vblank(data->drm_fd, primary->pipe->pipe);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &crc_limited);
+
+		/* Verify that the CRC of the software computed output is
+		 * equal to the CRC of the CTM matrix transformation output.
+		 */
+		igt_assert_crc_equal(&crc_full, &crc_limited);
+	}
+
+	free(gamma_linear);
+	free(degamma_linear);
+}
+#endif
+
+static void
+run_tests_for_pipe(data_t *data, enum pipe p)
+{
+	igt_output_t *output;
+	igt_pipe_t *pipe;
+	igt_plane_t *primary;
+	color_t red_green_blue[] = {
+		{ 1.0, 0.0, 0.0 },
+		{ 0.0, 1.0, 0.0 },
+		{ 0.0, 0.0, 1.0 }
+	};
+
+	igt_fixture {
+		igt_require_pipe_crc();
+
+		if (p >= data->display.n_pipes)
+			return;
+
+		pipe = &data->display.pipes[p];
+		if (pipe->n_planes < IGT_PLANE_PRIMARY)
+			return;
+
+		primary = &pipe->planes[IGT_PLANE_PRIMARY];
+
+		data->pipe_crc = igt_pipe_crc_new(primary->pipe->pipe,
+						  INTEL_PIPE_CRC_SOURCE_AUTO);
+
+		igt_assert(igt_pipe_get_property(&data->display.pipes[p],
+						 "DEGAMMA_LUT_SIZE",
+						 NULL,
+						 &data->degamma_lut_size,
+						 NULL));
+		igt_assert(igt_pipe_get_property(&data->display.pipes[p],
+						 "GAMMA_LUT_SIZE",
+						 NULL,
+						 &data->gamma_lut_size,
+						 NULL));
+
+		for_each_connected_output(&data->display, output) {
+			output_set_property_enum(output, "Broadcast RGB", "Full");
+			igt_output_set_pipe(output, primary->pipe->pipe);
+		}
+	}
+
+	igt_subtest_f("ctm-red-to-blue-pipe%d", p) {
+		color_t blue_green_blue[] = {
+			{ 0.0, 0.0, 1.0 },
+			{ 0.0, 1.0, 0.0 },
+			{ 0.0, 0.0, 1.0 }
+		};
+		float ctm[] = { 0.0, 0.0, 0.0,
+				0.0, 1.0, 0.0,
+				1.0, 0.0, 1.0 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      blue_green_blue, ctm);
+	}
+
+	igt_subtest_f("ctm-green-to-red-pipe%d", p) {
+		color_t red_red_blue[] = {
+			{ 1.0, 0.0, 0.0 },
+			{ 1.0, 0.0, 0.0 },
+			{ 0.0, 0.0, 1.0 }
+		};
+		float ctm[] = { 1.0, 1.0, 0.0,
+				0.0, 0.0, 0.0,
+				0.0, 0.0, 1.0 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      red_red_blue, ctm);
+	}
+
+	igt_subtest_f("ctm-blue-to-red-pipe%d", p) {
+		color_t red_green_red[] = {
+			{ 1.0, 0.0, 0.0 },
+			{ 0.0, 1.0, 0.0 },
+			{ 1.0, 0.0, 0.0 }
+		};
+		float ctm[] = { 1.0, 0.0, 1.0,
+				0.0, 1.0, 0.0,
+				0.0, 0.0, 0.0 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      red_green_red, ctm);
+	}
+
+	igt_subtest_f("ctm-0-25-pipe%d", p) {
+		float val = 63.0 / 255.0;
+		color_t red_green_blue_half[] = {
+			{ val, 0.0, 0.0 },
+			{ 0.0, val, 0.0 },
+			{ 0.0, 0.0, val }
+		};
+		float ctm[] = { 0.25, 0.0, 0.0,
+				0.0, 0.25, 0.0,
+				0.0, 0.0, 0.25 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      red_green_blue_half, ctm);
+	}
+
+	igt_subtest_f("ctm-0-5-pipe%d", p) {
+		float val = 127.0 / 255.0;
+		color_t red_green_blue_half[] = {
+			{ val, 0.0, 0.0 },
+			{ 0.0, val, 0.0 },
+			{ 0.0, 0.0, val }
+		};
+		float ctm[] = { 0.5, 0.0, 0.0,
+				0.0, 0.5, 0.0,
+				0.0, 0.0, 0.5 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      red_green_blue_half, ctm);
+	}
+
+	igt_subtest_f("ctm-0-75-pipe%d", p) {
+		float val = 191.0 / 255.0;
+		color_t red_green_blue_half[] = {
+			{ val, 0.0, 0.0 },
+			{ 0.0, val, 0.0 },
+			{ 0.0, 0.0, val }
+		};
+		float ctm[] = { 0.75, 0.0, 0.0,
+				0.0, 0.75, 0.0,
+				0.0, 0.0, 0.75 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      red_green_blue_half, ctm);
+	}
+
+	igt_subtest_f("ctm-negative-pipe%d", p) {
+		color_t all_black[] = {
+			{ 0.0, 0.0, 0.0 },
+			{ 0.0, 0.0, 0.0 },
+			{ 0.0, 0.0, 0.0 }
+		};
+		float ctm[] = { -1.0,  0.0,  0.0,
+				 0.0, -1.0,  0.0,
+				 0.0,  0.0, -1.0 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      all_black, ctm);
+	}
+
+	igt_subtest_f("ctm-max-pipe%d", p) {
+		color_t full_rgb[] = {
+			{ 1.0, 0.0, 0.0 },
+			{ 0.0, 1.0, 0.0 },
+			{ 0.0, 0.0, 1.0 }
+		};
+		float ctm[] = { 100.0,   0.0,   0.0,
+				  0.0, 100.0,   0.0,
+				  0.0,   0.0, 100.0 };
+		test_pipe_ctm(data, primary, red_green_blue,
+			      full_rgb, ctm);
+	}
+
+#if 0
+	igt_subtest_f("ctm-limited-range-pipe%d", p)
+		test_pipe_limited_range_ctm(data, primary);
+#endif
+
+	igt_subtest_f("degamma-pipe%d", p)
+		test_pipe_degamma(data, primary);
+
+	igt_subtest_f("gamma-pipe%d", p)
+		test_pipe_gamma(data, primary);
+
+	igt_subtest_f("legacy-gamma-pipe%d", p)
+		test_pipe_legacy_gamma(data, primary);
+
+	igt_fixture {
+		for_each_connected_output(&data->display, output) {
+			output_set_property_enum(output, "Broadcast RGB", "Full");
+			igt_output_set_pipe(output, PIPE_ANY);
+		}
+
+		disable_degamma(primary->pipe);
+		disable_gamma(primary->pipe);
+		disable_ctm(primary->pipe);
+		igt_display_commit(&data->display);
+
+		igt_pipe_crc_free(data->pipe_crc);
+		data->pipe_crc = NULL;
+	}
+}
+
+static int
+pipe_set_property_blob(igt_pipe_t *pipe, const char *property, void *ptr, size_t length)
+{
+	int ret = 0;
+	uint32_t prop_id;
+	uint32_t blob_id = 0;
+
+	igt_assert(kmstest_get_property(pipe->display->drm_fd,
+					pipe->crtc_id,
+					DRM_MODE_OBJECT_CRTC,
+					property,
+					&prop_id, NULL, NULL));
+
+	if (length > 0)
+		igt_assert_eq(drmModeCreatePropertyBlob(pipe->display->drm_fd,
+							ptr, length,
+							&blob_id), 0);
+
+	ret = drmModeObjectSetProperty(pipe->display->drm_fd,
+				       pipe->crtc_id,
+				       DRM_MODE_OBJECT_CRTC,
+				       prop_id, blob_id);
+
+	if (blob_id != 0)
+		igt_assert_eq(drmModeDestroyPropertyBlob(pipe->display->drm_fd, blob_id), 0);
+
+	return ret;
+}
+
+static void
+invalid_lut_sizes(data_t *data)
+{
+	igt_pipe_t *pipe = &data->display.pipes[0];
+	size_t degamma_lut_size = data->degamma_lut_size * sizeof(struct _drm_color_lut);
+	size_t gamma_lut_size = data->gamma_lut_size * sizeof(struct _drm_color_lut);
+
+	struct _drm_color_lut *degamma_lut = malloc(data->degamma_lut_size * sizeof(struct _drm_color_lut) * 2);
+	struct _drm_color_lut *gamma_lut = malloc(data->gamma_lut_size * sizeof(struct _drm_color_lut) * 2);
+
+	igt_assert_eq(pipe_set_property_blob(pipe, "DEGAMMA_LUT",
+					     degamma_lut, 1), -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "DEGAMMA_LUT",
+					     degamma_lut, degamma_lut_size + 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "DEGAMMA_LUT",
+					     degamma_lut, degamma_lut_size - 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "DEGAMMA_LUT",
+					     degamma_lut, degamma_lut_size + sizeof(struct _drm_color_lut)),
+		      -EINVAL);
+
+	igt_assert_eq(pipe_set_property_blob(pipe, "GAMMA_LUT",
+					     gamma_lut, 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "GAMMA_LUT",
+					     gamma_lut, gamma_lut_size + 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "GAMMA_LUT",
+					     gamma_lut, gamma_lut_size - 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "GAMMA_LUT",
+					     gamma_lut, gamma_lut_size + sizeof(struct _drm_color_lut)),
+		      -EINVAL);
+
+	free(degamma_lut);
+	free(gamma_lut);
+}
+
+static void
+invalid_ctm_matrix_sizes(data_t *data)
+{
+	igt_pipe_t *pipe = &data->display.pipes[0];
+	void *ptr = malloc(sizeof(struct _drm_color_ctm) * 4);
+
+	igt_assert_eq(pipe_set_property_blob(pipe, "CTM_MATRIX", ptr, 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "CTM_MATRIX", ptr,
+					     sizeof(struct _drm_color_ctm) + 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "CTM_MATRIX", ptr,
+					     sizeof(struct _drm_color_ctm) - 1),
+		      -EINVAL);
+	igt_assert_eq(pipe_set_property_blob(pipe, "CTM_MATRIX", ptr,
+					     sizeof(struct _drm_color_ctm) * 2),
+		      -EINVAL);
+
+	free(ptr);
+}
+
+igt_main
+{
+	data_t data = {};
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+		kmstest_set_vt_graphics_mode();
+
+		igt_display_init(&data.display, data.drm_fd);
+	}
+
+	/* We assume an 8bits depth per color framebuffer. */
+	data.color_depth = 8;
+
+	for (int pipe = 0; pipe < I915_MAX_PIPES; pipe++)
+		run_tests_for_pipe(&data, pipe);
+
+	igt_subtest_f("invalid-lut-sizes")
+		invalid_lut_sizes(&data);
+
+	igt_subtest_f("invalid-ctm-matrix-sizes")
+		invalid_ctm_matrix_sizes(&data);
+
+	igt_fixture {
+		igt_display_fini(&data.display);
+	}
+}
-- 
2.6.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes
  2016-02-01 15:34 [PATCH i-g-t 0/4] New pipe level color management tests V3 Lionel Landwerlin
@ 2016-02-01 15:34 ` Lionel Landwerlin
  0 siblings, 0 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-02-01 15:34 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_kms.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_kms.h | 17 +++++++++++++-
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index dd4ca45..22996d5 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -1179,6 +1179,21 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 						   &prop_value,
 						   NULL);
 				pipe->background = (uint32_t)prop_value;
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "DEGAMMA_LUT",
+						  &pipe->degamma_property,
+						  NULL,
+					  NULL);
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "CTM_MATRIX",
+						  &pipe->ctm_property,
+						  NULL,
+						  NULL);
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "GAMMA_LUT",
+						  &pipe->gamma_property,
+						  NULL,
+						  NULL);
 			}
 		}
 	}
@@ -1328,6 +1343,16 @@ static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, enum igt_plane plane)
 	return &pipe->planes[idx];
 }
 
+bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
+			   uint32_t *prop_id, uint64_t *value,
+			   drmModePropertyPtr *prop)
+{
+	return get_crtc_property(pipe->display->drm_fd,
+				 pipe->crtc_id,
+				 name,
+				 prop_id, value, prop);
+}
+
 static uint32_t igt_plane_get_fb_id(igt_plane_t *plane)
 {
 	if (plane->fb)
@@ -1635,6 +1660,17 @@ static int igt_output_commit(igt_output_t *output,
 		pipe->background_changed = false;
 	}
 
+	if (pipe->color_mgmt_changed) {
+		igt_crtc_set_property(output, pipe->degamma_property,
+				      pipe->degamma_blob);
+		igt_crtc_set_property(output, pipe->ctm_property,
+				      pipe->ctm_blob);
+		igt_crtc_set_property(output, pipe->gamma_property,
+				      pipe->gamma_blob);
+
+		pipe->color_mgmt_changed = false;
+	}
+
 	for (i = 0; i < pipe->n_planes; i++) {
 		igt_plane_t *plane = &pipe->planes[i];
 
@@ -1967,6 +2003,44 @@ void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation)
 	plane->rotation_changed = true;
 }
 
+static void
+igt_pipe_replace_blob(igt_pipe_t *pipe, uint64_t *blob, void *ptr, size_t length)
+{
+	igt_display_t *display = pipe->display;
+	uint32_t blob_id = 0;
+
+	if (*blob != 0)
+		igt_assert(drmModeDestroyPropertyBlob(display->drm_fd,
+						      *blob) == 0);
+
+	if (length > 0)
+		igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
+						     ptr, length, &blob_id) == 0);
+
+	*blob = blob_id;
+}
+
+void
+igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->degamma_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
+void
+igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->ctm_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
+void
+igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->gamma_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
 /**
  * igt_crtc_set_background:
  * @pipe: pipe pointer to which background color to be set
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 77327c2..11a37d5 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -215,6 +215,15 @@ struct igt_pipe {
 	uint64_t background; /* Background color MSB BGR 16bpc LSB */
 	uint32_t background_changed : 1;
 	uint32_t background_property;
+
+	uint64_t degamma_blob;
+	uint32_t degamma_property;
+	uint64_t ctm_blob;
+	uint32_t ctm_property;
+	uint64_t gamma_blob;
+	uint32_t gamma_property;
+	uint32_t color_mgmt_changed : 1;
+
 	uint32_t crtc_id;
 };
 
@@ -253,12 +262,19 @@ drmModeModeInfo *igt_output_get_mode(igt_output_t *output);
 void igt_output_override_mode(igt_output_t *output, drmModeModeInfo *mode);
 void igt_output_set_pipe(igt_output_t *output, enum pipe pipe);
 igt_plane_t *igt_output_get_plane(igt_output_t *output, enum igt_plane plane);
+bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
+			   uint32_t *prop_id, uint64_t *value,
+			   drmModePropertyPtr *prop);
 
 static inline bool igt_plane_supports_rotation(igt_plane_t *plane)
 {
 	return plane->rotation_property != 0;
 }
 
+void igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length);
+void igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length);
+void igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length);
+
 void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb);
 void igt_plane_set_position(igt_plane_t *plane, int x, int y);
 void igt_plane_set_size(igt_plane_t *plane, int w, int h);
@@ -294,4 +310,3 @@ const unsigned char* igt_kms_get_alt_edid(void);
 
 
 #endif /* __IGT_KMS_H__ */
-
-- 
2.7.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes
  2016-01-22 12:14 [PATCH i-g-t 0/4] New pipe level color management tests V2 Lionel Landwerlin
@ 2016-01-22 12:14 ` Lionel Landwerlin
  0 siblings, 0 replies; 7+ messages in thread
From: Lionel Landwerlin @ 2016-01-22 12:14 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_kms.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_kms.h | 17 +++++++++++++-
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index f5eef82..984d2ea 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -1136,6 +1136,21 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 						   &prop_value,
 						   NULL);
 				pipe->background = (uint32_t)prop_value;
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "DEGAMMA_LUT",
+						  &pipe->degamma_property,
+						  NULL,
+					  NULL);
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "CTM_MATRIX",
+						  &pipe->ctm_property,
+						  NULL,
+						  NULL);
+				get_crtc_property(display->drm_fd, output->config.crtc->crtc_id,
+						  "GAMMA_LUT",
+						  &pipe->gamma_property,
+						  NULL,
+						  NULL);
 			}
 		}
 	}
@@ -1285,6 +1300,16 @@ static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, enum igt_plane plane)
 	return &pipe->planes[idx];
 }
 
+bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
+			   uint32_t *prop_id, uint64_t *value,
+			   drmModePropertyPtr *prop)
+{
+	return get_crtc_property(pipe->display->drm_fd,
+				 pipe->crtc_id,
+				 name,
+				 prop_id, value, prop);
+}
+
 static uint32_t igt_plane_get_fb_id(igt_plane_t *plane)
 {
 	if (plane->fb)
@@ -1592,6 +1617,17 @@ static int igt_output_commit(igt_output_t *output,
 		pipe->background_changed = false;
 	}
 
+	if (pipe->color_mgmt_changed) {
+		igt_crtc_set_property(output, pipe->degamma_property,
+				      pipe->degamma_blob);
+		igt_crtc_set_property(output, pipe->ctm_property,
+				      pipe->ctm_blob);
+		igt_crtc_set_property(output, pipe->gamma_property,
+				      pipe->gamma_blob);
+
+		pipe->color_mgmt_changed = false;
+	}
+
 	for (i = 0; i < pipe->n_planes; i++) {
 		igt_plane_t *plane = &pipe->planes[i];
 
@@ -1924,6 +1960,44 @@ void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation)
 	plane->rotation_changed = true;
 }
 
+static void
+igt_pipe_replace_blob(igt_pipe_t *pipe, uint64_t *blob, void *ptr, size_t length)
+{
+	igt_display_t *display = pipe->display;
+	uint32_t blob_id = 0;
+
+	if (*blob != 0)
+		igt_assert(drmModeDestroyPropertyBlob(display->drm_fd,
+						      *blob) == 0);
+
+	if (length > 0)
+		igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
+						     ptr, length, &blob_id) == 0);
+
+	*blob = blob_id;
+}
+
+void
+igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->degamma_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
+void
+igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->ctm_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
+void
+igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length)
+{
+	igt_pipe_replace_blob(pipe, &pipe->gamma_blob, ptr, length);
+	pipe->color_mgmt_changed = 1;
+}
+
 /**
  * igt_crtc_set_background:
  * @pipe: pipe pointer to which background color to be set
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index c12c2e1..dc87981 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -212,6 +212,15 @@ struct igt_pipe {
 	uint64_t background; /* Background color MSB BGR 16bpc LSB */
 	uint32_t background_changed : 1;
 	uint32_t background_property;
+
+	uint64_t degamma_blob;
+	uint32_t degamma_property;
+	uint64_t ctm_blob;
+	uint32_t ctm_property;
+	uint64_t gamma_blob;
+	uint32_t gamma_property;
+	uint32_t color_mgmt_changed : 1;
+
 	uint32_t crtc_id;
 };
 
@@ -250,12 +259,19 @@ drmModeModeInfo *igt_output_get_mode(igt_output_t *output);
 void igt_output_override_mode(igt_output_t *output, drmModeModeInfo *mode);
 void igt_output_set_pipe(igt_output_t *output, enum pipe pipe);
 igt_plane_t *igt_output_get_plane(igt_output_t *output, enum igt_plane plane);
+bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
+			   uint32_t *prop_id, uint64_t *value,
+			   drmModePropertyPtr *prop);
 
 static inline bool igt_plane_supports_rotation(igt_plane_t *plane)
 {
 	return plane->rotation_property != 0;
 }
 
+void igt_pipe_set_degamma_lut(igt_pipe_t *pipe, void *ptr, size_t length);
+void igt_pipe_set_ctm_matrix(igt_pipe_t *pipe, void *ptr, size_t length);
+void igt_pipe_set_gamma_lut(igt_pipe_t *pipe, void *ptr, size_t length);
+
 void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb);
 void igt_plane_set_position(igt_plane_t *plane, int x, int y);
 void igt_plane_set_size(igt_plane_t *plane, int w, int h);
@@ -291,4 +307,3 @@ const unsigned char* igt_kms_get_alt_edid(void);
 
 
 #endif /* __IGT_KMS_H__ */
-
-- 
2.6.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-02-01 15:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-21 15:11 [PATCH i-g-t 0/4] New pipe level color management tests Lionel Landwerlin
2016-01-21 15:11 ` [PATCH i-g-t 1/4] lib: kms: add crtc_id to igt_pipe_t Lionel Landwerlin
2016-01-21 15:11 ` [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes Lionel Landwerlin
2016-01-21 15:11 ` [PATCH i-g-t 3/4] lib: fb: add igt_paint_color_gradient_range Lionel Landwerlin
2016-01-21 15:11 ` [PATCH i-g-t 4/4] tests/kms_color: New test for pipe level color management Lionel Landwerlin
2016-01-22 12:14 [PATCH i-g-t 0/4] New pipe level color management tests V2 Lionel Landwerlin
2016-01-22 12:14 ` [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes Lionel Landwerlin
2016-02-01 15:34 [PATCH i-g-t 0/4] New pipe level color management tests V3 Lionel Landwerlin
2016-02-01 15:34 ` [PATCH i-g-t 2/4] lib: kms: add helpers for color management properties on pipes Lionel Landwerlin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.