From: dhanyapr <dhanya....@intel.com>

This patch will verify color correction capability of a display driver.
Currently Pipe level CSC and Pipe level Gamma are supported.

Signed-off-by: dhanyapr <dhanya....@intel.com>
---
 tests/Makefile.sources |    1 +
 tests/kms_color.c      |  508 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 509 insertions(+)
 create mode 100644 tests/kms_color.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 994c31b..6211898 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -80,6 +80,7 @@ TESTS_progs_M = \
        kms_crtc_background_color \
        kms_plane_scaling \
        kms_panel_fitting \
+       kms_color \
        pm_lpsp \
        pm_rpm \
        pm_rps \
diff --git a/tests/kms_color.c b/tests/kms_color.c
new file mode 100644
index 0000000..df4ac06
--- /dev/null
+++ b/tests/kms_color.c
@@ -0,0 +1,508 @@
+/*
+ * Copyeight © 2013,2014 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 "drmtest.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+#include "igt_core.h"
+#include "intel_chipset.h"
+#include "igt_aux.h"
+#include<unistd.h>
+#include<stdlib.h>
+IGT_TEST_DESCRIPTION("Test Gamma at Plane/Pipe level");
+
+
+#define CHV_CSC_VALS    9
+#define DRM_IOCTL_MODE_CREATEPROPBLOB   DRM_IOWR(0xBD, struct 
drm_mode_create_blob)
+#define I915_PIPE_CSC           (1<<0)
+#define I915_PLANE_CSC  (1<<1)
+#define I915_CSC_COEFF_FORMAT_UNKNOWN   0
+#define I915_CSC_COEFF_FORMAT_CURRENT   0xFFFFFFFF
+#define I915_CSC_COEFF_FORMAT_S1_30     (1<<0)
+#define I915_CSC_COEFF_FORMAT_S2_29     (1<<1)
+
+#define CSC_MANTISSA_MAX_BITS    1
+#define CSC_MANTISSA_MAX_VALUE   ((1 << CSC_MANTISSA_MAX_BITS) - 1)
+#define CSC_FRACTION_MAX_BITS    10
+#define GAMMA_RED_SHIFT        16
+#define GAMMA_GREEN_SHIFT      8
+#define STANDARD_GAMMA                         2.2
+#define I915_GAMMA_FLAG_DEGAMMA                (1<<0)
+#define I915_PIPE_GAMMA                (1<<0)
+#define I915_PLANE_GAMMA       (1<<1)
+#define I915_GAMMA_PRECISION_UNKNOWN   0
+#define I915_GAMMA_PRECISION_CURRENT   0xFFFFFFFF
+#define I915_GAMMA_PRECISION_LEGACY    (1<<0)
+#define I915_GAMMA_PRECISION_10BIT     (1<<1)
+#define I915_GAMMA_PRECISION_12BIT     (1<<2)
+#define I915_GAMMA_PRECISION_14BIT     (1<<3)
+#define I915_GAMMA_PRECISION_16BIT     (1<<4)
+#define CHV_DEGAMMA_MAX_INDEX  64
+#define CHV_DEGAMMA_VALS       65
+#define CHV_8BIT_GAMMA_MAX_INDEX       256
+#define CHV_8BIT_GAMMA_MAX_VALS        CHV_8BIT_GAMMA_MAX_INDEX
+#define CHV_10BIT_GAMMA_MAX_INDEX      256
+#define CHV_10BIT_GAMMA_MAX_VALS       (CHV_10BIT_GAMMA_MAX_INDEX + 1)
+
+#define CHV_SPRITE_GAMMA_MAX_VALS      6
+#define DEFAULT 0
+#define RANDOM 1
+#define DRM_IOCTL_MODE_CREATEPROPBLOB  DRM_IOWR(0xBD, struct 
drm_mode_create_blob)
+
+struct drm_intel_csc{
+       uint32_t csc_level;
+       uint32_t csc_format;
+       uint32_t reserved;
+       uint64_t csc_matrix[9];
+
+};
+
+
+
+typedef struct{
+       int32_t brightness;
+       int32_t contrast;
+       float gamma;
+} CURVE_SLIDER_VALUES;
+
+typedef struct r16g16b16_pixel {
+       uint16_t red;
+       uint16_t green;
+       uint16_t blue;
+} rgb_pixel;
+
+struct drm_intel_gamma{
+       uint32_t flags;
+       uint32_t gamma_level;
+       uint32_t gamma_precision;
+       uint32_t num_samples;
+       uint32_t reserved;
+       rgb_pixel gamma_values[257];
+};
+
+static struct drm_mode_create_blob {
+       uint64_t data;
+       uint32_t length;
+       uint32_t blob_id;
+};
+
+
+typedef struct {
+       int fb_initial;
+       int drm_fd;
+       int w, h;
+       igt_display_t display;
+       struct igt_fb fb_prep;
+       struct igt_fb fb, fb1;
+} data_t;
+
+       static void
+paint_color(data_t *d, struct igt_fb *fb, uint16_t w, uint16_t h)
+{
+       cairo_t *cr;
+       cr = igt_get_cairo_ctx(d->drm_fd, fb);
+       igt_paint_test_pattern(cr, w, h);
+       cairo_destroy(cr);
+}
+
+int create_blob(int fd, uint64_t *data, int length)
+{
+       struct drm_mode_create_blob blob;
+       int ret = -1;
+       blob.data = (uint64_t)data;
+       blob.length = length;
+       blob.blob_id = -1;
+       ret = ioctl(fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &blob);
+       if (!ret)
+               return blob.blob_id;
+       printf("Blob creation ioctl failed");
+       return ret;
+}
+
+static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
+               igt_plane_t *plane, drmModeModeInfo *mode, enum 
igt_commit_style s)
+{
+       igt_display_t *display = &data->display;
+
+       igt_output_set_pipe(output, pipe);
+
+
+       /* before allocating, free if any older fb */
+       if (data->fb_initial) {
+               igt_remove_fb(data->drm_fd, &data->fb_prep);
+               data->fb_initial = 0;
+       }
+
+       /* allocate fb for plane 1 */
+       data->fb_initial = igt_create_color_fb(data->drm_fd,
+                       mode->hdisplay, mode->vdisplay,
+                       DRM_FORMAT_XRGB8888,
+                       LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */
+                       0, 0, 1.0,
+                       &data->fb_prep);
+       igt_assert(data->fb_initial);
+
+       igt_plane_set_fb(plane, &data->fb_prep);
+       if (s == COMMIT_LEGACY) {
+               int ret;
+               ret = drmModeSetCrtc(data->drm_fd,
+                               output->config.crtc->crtc_id,
+                               data->fb_initial,
+                               plane->pan_x, plane->pan_y,
+                               &output->id,
+                               1,
+                               mode);
+               igt_assert(ret == 0);
+       } else {
+               igt_display_commit2(display, s);
+       }
+}
+
+static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t 
*plane)
+{
+       igt_display_t *display = &data->display;
+
+       if (data->fb_initial) {
+               igt_remove_fb(data->drm_fd, &data->fb_prep);
+               data->fb_initial = 0;
+       }
+       if (data->fb.fb_id)
+               igt_remove_fb(data->drm_fd, &data->fb);
+       if (data->fb1.fb_id)
+               igt_remove_fb(data->drm_fd, &data->fb1);
+
+       if (!plane->is_primary) {
+               igt_plane_t *primary;
+
+               primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+               igt_plane_set_fb(primary, NULL);
+       }
+
+       igt_plane_set_fb(plane, NULL);
+       igt_output_set_pipe(output, PIPE_ANY);
+       igt_display_commit2(display, COMMIT_LEGACY);
+}
+
+int convertToBinarySigned(float value)
+{
+       int mantissa = 0;
+       int fraction = 0;
+       int sign = 0;
+       int loop;
+       float ftmp;
+       int ret = 0;
+       if (value < 0) {
+               sign = 1;
+               value *= (-1);
+       }
+       mantissa = (int) value / 1;
+       mantissa &= CSC_MANTISSA_MAX_VALUE;
+       ftmp = value - mantissa;
+       for (loop = 0; loop < CSC_FRACTION_MAX_BITS; loop++) {
+               ftmp = ftmp * 2;
+               if (ftmp >= 1) {
+                       fraction |= 0x1;
+                       ftmp -= 1.0;
+               }
+               if (loop == (CSC_FRACTION_MAX_BITS - 1)) {
+                       break;
+               } else {
+                       fraction <<= 1;
+               }
+       }
+       fraction &= 0x3FF;
+       ret = (fraction | (mantissa << CSC_FRACTION_MAX_BITS));
+       if (sign) {
+               ret = (~ret) + 1;
+       }
+       ret |= (sign << 11);
+       ret &= 0xFFF;
+       return ret;
+}
+void cscWrite(float *csc_val, uint64_t *csc_matrix)
+{
+       for (int i = 0; i < CHV_CSC_VALS; i++) {
+               csc_matrix[i] = (uint64_t)convertToBinarySigned(csc_val[i]);
+       }
+}
+
+void generateCurveFromSlider(CURVE_SLIDER_VALUES *pSlider, uint16_t *pCurve, 
uint32_t num_samples)
+{
+       double dGamma = (double)pSlider->gamma;
+       double dBrightness = (double)pSlider->brightness * 256;;
+       double dContrast = (double)pSlider->contrast;
+       double dSlope, dOutput, outVal;
+       uint32_t input, index, i;
+       int maxVal = 65535;
+       for (i = 0; i < num_samples*2; i++) {
+               outVal = (double)(255 * pow(((double)i / 255.0), 
(STANDARD_GAMMA / dGamma)));
+               outVal += 0.5;
+               if (maxVal < outVal) {
+                       outVal = maxVal;
+               }
+               pCurve[i] = outVal;
+       }
+       dSlope = 1.0 + dContrast / 100.0;
+       for (input = 0; input < num_samples*2; input++) {
+               dOutput = dSlope * pCurve[input];
+               dOutput += dBrightness + 0.5;
+               if (dOutput > maxVal)
+                       dOutput = maxVal;
+               if (dOutput < 0)
+                       dOutput = 0;
+               pCurve[input] = dOutput;
+       }
+}
+void writeCurveCsv(uint16_t *pCurveData, uint32_t num_samples, rgb_pixel 
*gamma_ptr)
+{
+       uint16_t *pRed, *pGreen, *pBlue;
+       uint64_t i, index;
+
+       pRed = pCurveData;
+       pGreen = pCurveData;
+       pBlue = pCurveData;
+       for (i = 0; i < num_samples; i++) {
+               index = i * 2;
+               gamma_ptr[i].red = pRed[index];
+               gamma_ptr[i].green = pGreen[index];
+               gamma_ptr[i].blue = pBlue[index];
+       }
+}
+
+void gammaPipe(int brightness, int contrast, float gamma, uint32_t 
num_samples, rgb_pixel *gamma_ptr)
+{
+       CURVE_SLIDER_VALUES sSlideData;
+       uint16_t pCurve[2*num_samples];
+
+       sSlideData.brightness = brightness;
+       sSlideData.contrast = contrast;
+       sSlideData.gamma = gamma;
+       generateCurveFromSlider(&sSlideData, pCurve, num_samples);
+       writeCurveCsv(pCurve, num_samples, gamma_ptr);
+}
+
+int set_color_property(int drm_fd, int id, int object, char *prop_name, int 
blob_id)
+{
+       int i = 0, res;
+
+       drmModeObjectPropertiesPtr props = NULL;
+
+       if (id < 0 || ((object != DRM_MODE_OBJECT_CRTC) && (object != 
DRM_MODE_OBJECT_PLANE))) {
+               printf("Invalid input to set color property (%d and %d)", id, 
object);
+               return -1;
+       }
+
+       props = drmModeObjectGetProperties(drm_fd, id, object);
+       if (!props) {
+               return -1;
+       }
+       for (i = 0; i < props->count_props; i++) {
+               drmModePropertyPtr prop = drmModeGetProperty(drm_fd, 
props->props[i]);
+               if (strcmp(prop->name, prop_name) == 0) {
+                       /* Found property, now set the values */
+                       res = drmModeObjectSetProperty(drm_fd, id, object, 
(uint32_t)prop->prop_id, blob_id);
+                       if (res) {
+                               drmModeFreeProperty(prop);
+                               drmModeFreeObjectProperties(props);
+                               return res;
+                       } else {
+                               drmModeFreeProperty(prop);
+                               break;
+                       }
+               }
+
+               drmModeFreeProperty(prop);
+       }
+       drmModeFreeObjectProperties(props);
+       if (i == props->count_props) {
+               /* Property not found */
+               printf("\nset_property \"%s\" No such property\n", prop_name);
+               return -1;
+       }
+       return 0;
+}
+void test_pipe_csc(igt_display_t *display, igt_output_t *output, igt_plane_t 
*plane, uint32_t csc_format, int value)
+{
+       struct drm_intel_csc *csc_data = NULL;
+       csc_data = (struct drm_intel_csc *) malloc(sizeof(struct 
drm_intel_csc));
+       csc_data->csc_level = I915_PIPE_CSC;
+       csc_data->csc_format = csc_format;
+       int64_t csc_matrix[CHV_CSC_VALS];
+       float  csc_val[CHV_CSC_VALS];
+       float csc_random[CHV_CSC_VALS] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
+       float csc_default[CHV_CSC_VALS] = {1, 0, 1, 0, 1, 0, 1, 0, 1};
+       int i, res;
+       if (value == DEFAULT)
+               memcpy(csc_val, csc_default, sizeof(csc_val));
+       else
+               memcpy(csc_val, csc_random, sizeof(csc_val));
+
+       cscWrite(csc_val, csc_matrix);
+
+       for (i = 0; i < CHV_CSC_VALS; i++) {
+               csc_data->csc_matrix[i] = csc_matrix[i];
+       }
+
+
+       int blob_id = create_blob(display->drm_fd, (uint64_t *)(csc_data), 
sizeof(struct drm_intel_csc));
+
+       igt_assert(blob_id > 0);
+
+       res = set_color_property(display->drm_fd, output->config.crtc->crtc_id, 
DRM_MODE_OBJECT_CRTC, "csc_property", blob_id);
+       if (res < 0) {
+               printf("Setting CSC failed!");
+       }
+       free(csc_data);
+
+
+}
+
+void test_pipe_gamma(igt_display_t *display, igt_output_t *output, igt_plane_t 
*plane, float gamma, int brightness, int contrast, uint32_t gamma_precision, 
uint32_t num_samples)
+{
+       struct drm_intel_gamma *gamma_data =  NULL;
+       int res;
+       gamma_data = malloc(sizeof(struct drm_intel_gamma) + (num_samples * 
sizeof(rgb_pixel)));
+       gamma_data->flags = 0;
+       gamma_data->gamma_level = I915_PIPE_GAMMA;
+       gamma_data->gamma_precision = gamma_precision;
+       gamma_data->num_samples = num_samples;
+       rgb_pixel gamma_ptr[num_samples];
+       gammaPipe(brightness, contrast, gamma, num_samples, gamma_ptr);
+       for (int i = 0; i < num_samples; i++) {
+               gamma_data->gamma_values[i] = gamma_ptr[i];
+       }
+
+
+       int blob_id = create_blob(display->drm_fd, (uint64_t *)(gamma_data), 
sizeof(struct drm_intel_gamma) + (num_samples * sizeof(rgb_pixel)));
+       igt_assert(blob_id > 0);
+       res = set_color_property(display->drm_fd, output->config.crtc->crtc_id, 
DRM_MODE_OBJECT_CRTC, "gamma_property", blob_id);
+       if (res < 0) {
+               printf("Setting Gamma failed!");
+       }
+       free(gamma_data);
+}
+void test_pipe_color(data_t *data, char *prop_name, int value)
+{
+       igt_display_t *display = &data->display;
+       igt_output_t *output;
+       igt_plane_t *plane;
+       enum pipe pipe;
+       enum igt_commit_style commit = COMMIT_LEGACY;
+       int res, i;
+       int fb_id, fb_id1;
+       int width, height;
+       uint32_t pixelformat = DRM_FORMAT_XRGB8888;
+       for_each_connected_output(display, output) {
+               drmModeModeInfo *mode;
+               pipe = output->config.pipe;
+               igt_output_set_pipe(output, pipe);
+               mode = igt_output_get_mode(output);
+               /*Draw the initial primary plane*/
+               plane = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+
+               prepare_crtc(data, output, pipe, plane, mode, commit);
+               plane = igt_output_get_plane(output, IGT_PLANE_2);
+               fb_id = igt_create_color_fb(data->drm_fd,
+                               width, height,
+                               pixelformat,
+                               LOCAL_DRM_FORMAT_MOD_NONE,
+                               1.0,
+                               0.0,
+                               0.0,
+                               &data->fb);
+               igt_assert(fb_id);
+               plane->crtc_x = 0;
+               plane->crtc_y = 0;
+               plane->fb_changed = true;
+               igt_plane_set_fb(plane, &data->fb);
+               /* set the width and height for sprite plane 2. */
+               width = 200;
+               height = 200;
+               plane = igt_output_get_plane(output, IGT_PLANE_3);
+               fb_id = igt_create_color_fb(data->drm_fd,
+                               width, height,
+                               pixelformat,
+                               LOCAL_DRM_FORMAT_MOD_NONE,
+                               0.0,
+                               0.0,
+                               1.0,
+                               &data->fb1);
+               igt_assert(fb_id);
+
+               plane->crtc_x = 30;
+               plane->crtc_y = 30;
+               plane->fb_changed = true;
+               igt_plane_set_fb(plane, &data->fb1);
+
+               igt_display_commit2(display, commit);
+               usleep(2000000);
+               if ((strcmp(prop_name, "gamma_property") == 0) && value == 
DEFAULT) {
+                       test_pipe_gamma(display, output, plane, 1, 50, 50, 
I915_GAMMA_PRECISION_LEGACY, CHV_8BIT_GAMMA_MAX_VALS);
+               } else  if ((strcmp(prop_name, "gamma_property") == 0) && value 
== RANDOM) {
+                       test_pipe_gamma(display, output, plane, 1.5, 10, 20, 
I915_GAMMA_PRECISION_LEGACY, CHV_8BIT_GAMMA_MAX_VALS);
+               } else  if ((strcmp(prop_name, "csc_property") == 0)) {
+                       test_pipe_csc(display, output, plane, 
I915_CSC_COEFF_FORMAT_S2_29, value);
+               } else {
+                       printf("Invalid Test\n");
+               }
+               plane = igt_output_get_plane(output, IGT_PLANE_3);
+               cleanup_crtc(data, output, plane);
+               plane = igt_output_get_plane(output, IGT_PLANE_2);
+               cleanup_crtc(data, output, plane);
+
+       }
+}
+
+igt_main
+{
+       data_t data = {};
+       int gen = 0;
+       int plane_it = 0, it_rotation = 0, it_tiling = 0;
+       igt_skip_on_simulation();
+
+       igt_fixture{
+               data.drm_fd = drm_open_any_master();
+
+               kmstest_set_vt_graphics_mode();
+
+               igt_display_init(&data.display, data.drm_fd);
+       }
+       igt_subtest_f("Enable_Gamma") {
+               test_pipe_color(&data, "gamma_property", RANDOM);
+       }
+       igt_subtest_f("Enable_Default_Gamma") {
+               test_pipe_color(&data, "gamma_property", DEFAULT);
+       }
+       igt_subtest_f("Enable_CSC") {
+               test_pipe_color(&data, "csc_property", RANDOM);
+       }
+       igt_subtest_f("Enable_Default_CSC") {
+               test_pipe_color(&data, "csc_property", DEFAULT);
+       }
+       igt_fixture{
+               igt_display_fini(&data.display);
+       }
+}
+
-- 
1.7.9.5

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

Reply via email to