[Intel-gfx] [PATCH] tests/kms_color:Color IGT

Thomas Wood thomas.wood at intel.com
Tue Nov 24 08:36:17 PST 2015


Please make sure your patch is tagged with "i-g-t" so it is correctly
identified by patchwork, as described in:

http://lists.freedesktop.org/archives/intel-gfx/2015-November/079712.html

It would also be helpful if the subject line briefly mentions what the
patch does.


On 20 November 2015 at 10:27, Dhanya Pillai <dhanya.p.r at intel.com> wrote:
> From: Dhanya <dhanya.p.r at intel.com>
>
> This patch will verify color correction capability of a display driver.
> Gamma/CSC/De-gamma verifications are supported.

I have made a few specific comments below about this patch, but it
would be good to include tests that verify the various features by
comparing CRCs of a reference image and the output pipe. This would
ensure that what is displayed on screen exactly corresponds to the
expected state.


>
> Signed-off-by: Dhanya <dhanya.p.r at intel.com>
> ---
>  tests/Makefile.sources |    1 +
>  tests/kms_color.c      | 1070 ++++++++++++++++++++++++++++++++++++++++++++++++

Please also add the binary name to .gitignore.


>  2 files changed, 1071 insertions(+)
>  create mode 100644 tests/kms_color.c
>
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 8fb2de8..906c14f 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -64,6 +64,7 @@ TESTS_progs_M = \
>         gem_write_read_ring_switch \
>         kms_addfb_basic \
>         kms_atomic \
> +       kms_color \
>         kms_cursor_crc \
>         kms_draw_crc \
>         kms_fbc_crc \
> diff --git a/tests/kms_color.c b/tests/kms_color.c
> new file mode 100644
> index 0000000..c261c3f
> --- /dev/null
> +++ b/tests/kms_color.c

This test produces a lot of compiler warnings and an error with the
default CFLAGS. I have not mentioned them individually below, but
please check and make sure the problems are addressed.


> @@ -0,0 +1,1070 @@
> +/*
> + * 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 "drmtest.h"
> +#include "drm.h"
> +#include "igt_debugfs.h"
> +#include "igt_kms.h"
> +#include "igt_core.h"
> +#include "intel_io.h"
> +#include "intel_chipset.h"
> +#include "igt_aux.h"
> +#include<unistd.h>
> +#include<stdlib.h>
> +#include <sys/ioctl.h>
> +#include <linux/types.h>
> +
> +
> +IGT_TEST_DESCRIPTION("Test Color Features at Pipe level");

It would be helpful if a more detailed description of the test could
also be included here as a comment, specifying what specific featues
are under test and how the results are verified.


> +typedef unsigned char u8;
> +typedef uint16_t u16;
> +typedef uint32_t u32;

These typedefs are not used anywhere, so can be removed.


> +
> +#define CSC_MAX_VALS    9
> +
> +#define GEN9_SPLITGAMMA_MAX_VALS                512
> +#define GEN9_8BIT_GAMMA_MAX_VALS                256
> +#define GEN9_10BIT_GAMMA_MAX_VALS               1024
> +#define GEN9_12BIT_GAMMA_MAX_VALS               513
> +#define BDW_MAX_GAMMA                         ((1 << 24) - 1)
> +
> +
> +#define CSC_COEFF_MAX   0x3FE000000
> +#define CSC_COEFF_MIN   0xFFFFFFFC00000000

The above defines are not used anywhere.


> +
> +#define VAR_LEN 100
> +/*OFFSETS*/
> +
> +#define _PIPE_A_CSC_COEFF 0x49010
> +#define _PIPE_B_CSC_COEFF 0x49110
> +#define GAMMA_8BIT_PIPEA  0x4A000
> +#define GAMMA_8BIT_PIPEB  0x4A800
> +#define GAMMA_8BIT_PIPEC  0x4B000
> +
> +#define GAMMA_10BIT_PIPEA  0x4A404
> +#define GAMMA_10BIT_PIPEB  0x4AC04
> +#define GAMMA_10BIT_PIPEC  0x4B404

The PIPEC defines are not used.


> +
> +#define CSC_TEST 0
> +#define GAMMA_TEST 1
> +#define DEGAMMA_TEST 2
> +#define ENABLE 0
> +#define DISABLE 1
> +#define RED 0
> +#define GREEN 1
> +#define BLUE 2
> +#define UNITY 3
> +#define GAMMA_1 0
> +#define GAMMA_2 1
> +#define GAMMA_2_2 2
> +#define PRIMARY 0
> +#define SECONDARY 1

The SECONDARY define is not used, and the PRIMARY define appears to be
used in two different contexts. Could this be clarified?


> +
> +#define CSC_COEFF_UNITY 0x100000000
> +
> +#define GET_BIT_MASK(n) ((1 << n) - 1)
> +#define GET_BITS(x, start, nbits) ((x >> start) & GET_BIT_MASK(nbits))
> +#define GET_BITS_ROUNDOFF(x, start, nbits) \
> +       ((GET_BITS(x, start, (nbits + 1)) + 1) >> 1)
> +
> +/*Structure defination will be removed once intergrated in libdrm */

These are usually prefixed with local_ so that the test will continue
to compile when using a libdrm version that does include the new
definitions.


> +struct drm_r32g32b32 {
> +       __u32 r32;
> +       __u32 g32;
> +       __u32 b32;
> +       __u32 reserved;
> +};
> +
> +struct drm_palette {
> +       struct drm_r32g32b32 lut[0];
> +};
> +
> +struct drm_ctm {
> +       __s64 ctm_coeff[9];
> +};
> +
> +float ctm_red[9] = {1, 1, 1, 0, 0, 0, 0, 0, 0};
> +float ctm_green[9] = {0, 0, 0, 1, 1, 1, 0, 0, 0};
> +float ctm_blue[9] = {0, 0, 0, 0, 0, 0, 1, 1, 1};
> +float ctm_unity[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
> +
> +struct data_t {
> +       int fb_initial;
> +       int drm_fd;
> +       int gen;
> +       int w, h;
> +       igt_display_t display;
> +       struct igt_fb fb_prep;
> +       struct igt_fb fb, fb1;
> +};
> +
> +
> +static 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;
> +       igt_info("Blob creation ioctl failed");
> +       return ret;

Since the test will always fail after this, it is probably better to
fail directly in this function using igt_fail_on_f.


> +}
> +
> +static void prepare_crtc(struct data_t *data, igt_output_t *output,
> +               enum pipe pipe, igt_plane_t *plane, drmModeModeInfo *mode,
> +               enum igt_commit_style s)

When function parameters wrap onto new lines, they should generally be
aligned under the opening bracket.


> +{
> +       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,

As above, function parameters should be aligned under the opening bracket.


> +                       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);
> +
> +               igt_display_commit2(display, s);

Wrong indent here.


> +}

Please make sure there is a blank line between functions.


> +static void cleanup_fb(struct data_t *data)
> +{
> +       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);
> +
> +}
> +static void cleanup_crtc(struct data_t *data, igt_output_t *output,
> +               igt_plane_t *plane)
> +{
> +       igt_display_t *display = &data->display;
> +
> +       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_UNIVERSAL);
> +
> +}
> +
> +
> +
> +static int get_color_property(int drm_fd, int id, int object,
> +               char *prop_name, int blob_id)
> +{
> +       int i = 0, ret = 0;
> +       uint64_t value = 0;
> +       struct drm_palette *gamma_data = NULL;
> +       drmModeObjectPropertiesPtr props = NULL;
> +
> +       if (id < 0 || ((object != DRM_MODE_OBJECT_CRTC) &&
> +                               (object != DRM_MODE_OBJECT_PLANE))) {
> +               igt_warn("Invalid input to get color property %d", id);
> +               return -1;

This pattern (igt_warn and return -1) is repeated a few times in this
function and in set_color_property, but should probably always cause
the test to fail. Using the appropriate igt_assert_f or igt_fail_on_f
macros here may produce better failure messages and mean the test
fails faster when there is a problem.


> +       }
> +       value = blob_id;
> +
> +       props = drmModeObjectGetProperties(drm_fd, id, object);
> +       if (!props) {
> +               igt_warn("\nNo property for object id=%d\n", id);
> +               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) {
> +                       blob_id = props->prop_values[i];
> +                       break;
> +               }
> +               drmModeFreeProperty(prop);
> +       }
> +
> +       ret = blob_id;
> +       drmModeFreeObjectProperties(props);
> +       if (i == props->count_props) {
> +               igt_warn("%s No such property\n", prop_name);
> +               return -1;
> +       }
> +       return ret;
> +}
> +
> +
> +static 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))) {
> +               igt_warn("Invalid input to set color property %d", id);
> +               return -1;
> +       }
> +
> +       props = drmModeObjectGetProperties(drm_fd, id, object);
> +       if (!props) {
> +               igt_warn("\nNo property for object id=%d\n", id);
> +               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) {
> +                       res = drmModeObjectSetProperty(drm_fd, id, object,
> +                                       (uint32_t)prop->prop_id, blob_id);
> +
> +                       if (res) {
> +                               drmModeFreeProperty(prop);
> +                               drmModeFreeObjectProperties(props);
> +                       } else {
> +                               drmModeFreeProperty(prop);
> +                               break;
> +                       }
> +               }
> +
> +               drmModeFreeProperty(prop);
> +       }
> +       drmModeFreeObjectProperties(props);
> +       if (i == props->count_props) {
> +               igt_warn("%s No such property\n", prop_name);

Should the test skip rather than fail in this case?


> +               return -1;
> +       }
> +       return 0;
> +}
> +static int64_t  convertFloatToBinary(double input)
> +{
> +
> +       int integer_part, count = 0;
> +       uint32_t temp_ip, frac_val = 0x00000000;
> +       uint64_t integer_val = 0x00000000;
> +       int64_t  value = 0x0000000000000000;
> +       float fractional_part, ip;
> +       integer_part = (int)input;
> +       fractional_part = input - integer_part;
> +       while (fractional_part != 0.000000) {
> +               ip = fractional_part * 16;
> +               temp_ip = (int)(fractional_part * 16);
> +               frac_val = frac_val | (temp_ip << (28 - count * 4));
> +               count++;
> +               fractional_part = ip - temp_ip;
> +       }
> +       integer_val = integer_part;
> +       value = value | (integer_val << 32);
> +       value = value | frac_val;
> +       return value;
> +
> +
> +}
> +static void write_gamma_lut(int brightness, int contrast, int gamma, uint32_t num_samples,
> +               struct drm_r32g32b32 *gamma_ptr)
> +{
> +       unsigned short Red, Green, Blue;
> +       uint32_t r32, b32, g32;
> +       uint64_t i, index, val;
> +       uint32_t data[num_samples];
> +
> +       for (i = 0; i < num_samples; i++) {
> +               data[i] = (brightness +  contrast * pow((double)i, (double)gamma)) * num_samples;
> +               Blue = data[i];
> +               Green = data[i] >> 8;
> +               Red = data[i] >> 16;
> +               r32 = Red  << 16;
> +               b32 = Blue ;
> +               g32 = Green << 8;
> +               gamma_ptr[i].r32 = r32;
> +               gamma_ptr[i].g32 = g32;
> +               gamma_ptr[i].b32 = b32;
> +               val = 0;
> +               val = r32;
> +               val <<= 8;
> +               val = val | g32;
> +               val <<= 8;
> +               val = val | b32;
> +       }
> +}
> +static uint64_t get_blob(int fd, int blob_id, int length)
> +{
> +       struct drm_mode_get_blob blob;
> +       int ret = 0;
> +       int count = 0;
> +
> +       blob.blob_id = blob_id;
> +       blob.length = length;
> +       blob.data = (uint64_t) malloc(blob.length);
> +       ret = ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob);
> +
> +       if (ret)
> +               igt_info("GET BLOB Failed\n");

Should this be igt_fail_on_f?


> +
> +       return blob.data;
> +}
> +
> +static uint32_t csc_coeff(int64_t coeff)
> +{
> +       uint32_t reg_val, ls_bit_pos, exponent_bits, sign_bit = 0;
> +       int32_t mantissa;
> +       uint64_t abs_coeff;
> +
> +       abs_coeff = coeff;
> +       if (abs_coeff < (CSC_COEFF_UNITY >> 3)) {
> +               exponent_bits = 3;
> +               ls_bit_pos = 19;
> +       } else if (abs_coeff >= (CSC_COEFF_UNITY >> 3) &&
> +                       abs_coeff < (CSC_COEFF_UNITY >> 2)) {
> +               exponent_bits = 2;
> +               ls_bit_pos = 20;
> +       } else if (abs_coeff >= (CSC_COEFF_UNITY >> 2)
> +                       && abs_coeff < (CSC_COEFF_UNITY >> 1)) {
> +               exponent_bits = 1;
> +               ls_bit_pos = 21;
> +       } else if (abs_coeff >= (CSC_COEFF_UNITY >> 1)
> +                       && abs_coeff < CSC_COEFF_UNITY) {
> +               exponent_bits = 0;
> +               ls_bit_pos = 22;
> +       } else if (abs_coeff >= CSC_COEFF_UNITY &&
> +                       abs_coeff < (CSC_COEFF_UNITY << 1)) {
> +               exponent_bits = 7;
> +               ls_bit_pos = 23;
> +       } else {
> +               exponent_bits = 6;
> +               ls_bit_pos = 24;
> +       }
> +       mantissa = GET_BITS_ROUNDOFF(abs_coeff, ls_bit_pos, CSC_MAX_VALS);
> +       if (coeff < 0)
> +               sign_bit = 1;
> +
> +       reg_val = 0;
> +       reg_val |= (exponent_bits << 12);
> +       reg_val |= mantissa << 3;
> +       reg_val |= sign_bit << 15;
> +       return reg_val;
> +}
> +
> +static bool validate_ctm_registers(int display, int64_t value[CSC_MAX_VALS])
> +{
> +       uint32_t temp_reg_val = 0, RValue = 0, OFFSET;
> +       uint32_t tmp_val, tmp2_val;
> +       bool result = false;
> +       uint32_t RY_Val = 0, GY_Val = 0, BY_Val = 0;
> +       uint32_t RU_Val = 0, GU_Val = 0, BU_Val = 0;
> +       uint32_t RV_Val = 0, GV_Val = 0, BV_Val = 0;
> +       char register_to_validate[VAR_LEN];
> +       intel_register_access_init(intel_get_pci_device(), 0);
> +
> +       if (display == PRIMARY)
> +               OFFSET = _PIPE_A_CSC_COEFF;
> +       else
> +               OFFSET = _PIPE_B_CSC_COEFF;
> +
> +       temp_reg_val = INREG(OFFSET);
> +       GY_Val = temp_reg_val & 0xFFFF;
> +       tmp_val = csc_coeff(value[1]);
> +       if (GY_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", GY_Val, tmp_val, value[1]);
> +               return result;

Returning from the function here (and in similar places below) will
mean igt_register_access_fini is not called. There is a similar issue
in gamma_register_validation.


> +       }
> +       RY_Val = (temp_reg_val >> 16) & 0xFFFF;
> +       tmp_val = csc_coeff(value[0]);
> +       if (RY_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[0]);
> +               return result;
> +       }
> +       OFFSET += 4;
> +       temp_reg_val = INREG(OFFSET);
> +       BY_Val = (temp_reg_val >> 16) & 0xFFFF;
> +       tmp_val = csc_coeff(value[2]);
> +       if (BY_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[2]);
> +               return result;
> +       }
> +       OFFSET += 4;
> +       temp_reg_val = INREG(OFFSET);
> +       RU_Val = (temp_reg_val  >> 16) & 0xFFFF;
> +       tmp_val = csc_coeff(value[3]);
> +       if (RU_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[3]);
> +               return result;
> +       }
> +       GU_Val = temp_reg_val & 0xFFFF;
> +       tmp_val = csc_coeff(value[4]);
> +       if (GU_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[4]);
> +               return result;
> +       }
> +       OFFSET += 4;
> +       temp_reg_val = INREG(OFFSET);
> +       BU_Val = (temp_reg_val >> 16) & 0xFFFF;
> +       tmp_val = csc_coeff(value[5]);
> +       if (BU_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[5]);
> +               return result;
> +       }
> +       OFFSET += 4;
> +       temp_reg_val = INREG(OFFSET);
> +       RV_Val = (temp_reg_val >> 16) & 0xFFFF;
> +       tmp_val = csc_coeff(value[6]);
> +       if (RV_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[6]);
> +               return result;
> +       }
> +       GV_Val = temp_reg_val  & 0xFFFF;
> +       tmp_val = csc_coeff(value[7]);
> +       if (GV_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[7]);
> +               return result;
> +       }
> +       OFFSET += 4;
> +       temp_reg_val = INREG(OFFSET);
> +       BV_Val = (temp_reg_val >> 16) & 0xFFFF;
> +       tmp_val = csc_coeff(value[8]);
> +       if (BV_Val != tmp_val) {
> +               igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[8]);
> +               return result;
> +       }
> +
> +       igt_info("CTM Register test for Coefficient is PASS \n");
> +       intel_register_access_fini();
> +
> +       return true;
> +}
> +static void enable_plane(struct data_t *data, igt_display_t *display, igt_output_t *output, int pipe1)
> +{
> +       enum igt_commit_style commit;
> +       int res, i;
> +       int fb_id, fb_id1;
> +       int width, height;
> +       uint32_t pixelformat = DRM_FORMAT_XRGB8888;
> +       commit = COMMIT_UNIVERSAL;
> +       enum pipe pipe;
> +       for_each_connected_output(display, output) {
> +               drmModeModeInfo *mode;
> +               pipe = output->config.pipe;
> +
> +               if (pipe != pipe1)
> +                       break;
> +               igt_plane_t *plane;
> +               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);
> +               /*Random Size  Buffer Creation */
> +               width = 600;
> +               height = 600;
> +
> +               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,
> +                               0.0,
> +                               1.0,
> +                               0.0,
> +                               &data->fb);
> +               igt_plane_set_position(plane, 100, 100);
> +
> +               igt_plane_set_fb(plane, &data->fb);
> +               igt_display_commit2(display, commit);
> +       }
> +
> +}
> +static void test_pipe_csc(struct data_t *data, igt_display_t *display, igt_output_t *output,
> +               igt_plane_t *plane, int enable, int value, int pipe1)
> +{
> +       struct drm_ctm *ctm_data = NULL;
> +       bool ret = false;
> +       ctm_data = (struct drm_ctm *)
> +               malloc(sizeof(struct drm_ctm));
> +       enum igt_commit_style commit;
> +       int res, i;
> +       int fb_id, fb_id1;
> +       int width, height;
> +       uint32_t pixelformat = DRM_FORMAT_XRGB8888;
> +       commit = COMMIT_UNIVERSAL;
> +       float *ctm;
> +       enum pipe pipe;
> +       if (!enable)
> +               ctm = ctm_unity;
> +       else {
> +               if (value == RED) {
> +                       ctm = ctm_red;
> +               } else if (value == GREEN) {
> +                       ctm = ctm_green;
> +               } else if (value == BLUE) {
> +                       ctm = ctm_blue;
> +               } else{
> +                       ctm = ctm_unity;
> +               } }
> +       for (i = 0; i < CSC_MAX_VALS; i++) {
> +               ctm_data->ctm_coeff[i] = convertFloatToBinary(*(ctm + i));
> +       }
> +
> +       int blob_id = create_blob(display->drm_fd,
> +                       (int *)(ctm_data), sizeof(struct drm_ctm));
> +       if (blob_id < 0) {
> +               igt_warn("CTM:BLOB IOCTL Fail\n");
> +       }
> +       igt_assert_lte(0, blob_id);
> +       res = set_color_property(display->drm_fd, output->config.crtc->crtc_id,
> +                       DRM_MODE_OBJECT_CRTC, "CTM", blob_id);
> +       if (res < 0)
> +               igt_warn("CTM:Set Property Failed\n");
> +       igt_assert_lte(0, res);
> +       res = get_color_property(display->drm_fd, output->config.crtc->crtc_id, DRM_MODE_OBJECT_CRTC, "CTM", blob_id);
> +       if (res < 0)
> +               igt_warn("CTM:Get Property Failed\n");
> +       igt_assert_lte(0, res);
> +       uint64_t blob_address = get_blob(display->drm_fd, res, sizeof(struct drm_ctm));
> +       ctm_data = (struct drm_ctm *) (intptr_t) blob_address;
> +       i = 0;
> +       enable_plane(data, display, output, pipe1);
> +       /*Register Verification*/
> +       ret = validate_ctm_registers(pipe1, ctm_data->ctm_coeff);
> +       if (!ret)
> +               igt_warn("Register Verification Failed for CTM");
> +       free(ctm_data);
> +       igt_assert(ret);
> +
> +
> +}
> +
> +static bool gamma_register_validation(int pipe, int mode, struct drm_r32g32b32 gamma_lut[mode])
> +{
> +       uint16_t blue_fract, green_fract, red_fract, blue_fract1, green_fract1, red_fract1, blue_fract2, green_fract2, red_fract2;
> +       int ret, count, num_samples, length;
> +       uint32_t blue, green, red, word, index, odd_word, even_word;
> +       uint32_t offset, gamma;
> +       intel_register_access_init(intel_get_pci_device(), 0);
> +
> +       if (pipe == PRIMARY) {
> +               if (mode == GEN9_8BIT_GAMMA_MAX_VALS)
> +                       offset = GAMMA_8BIT_PIPEA;
> +               else
> +                       offset = GAMMA_10BIT_PIPEA;
> +       } else {
> +               if (mode == GEN9_8BIT_GAMMA_MAX_VALS)
> +                       offset = GAMMA_8BIT_PIPEB;
> +               else
> +                       offset = GAMMA_10BIT_PIPEB;
> +       }
> +
> +       switch (mode) {
> +       case 0:
> +               return true;
> +       case GEN9_8BIT_GAMMA_MAX_VALS:
> +               count = 0;
> +               while (count < GEN9_8BIT_GAMMA_MAX_VALS) {
> +                       blue = gamma_lut[count].b32;
> +                       green = gamma_lut[count].g32;
> +                       red = gamma_lut[count].r32;
> +                       if (blue >= BDW_MAX_GAMMA)
> +                               blue = BDW_MAX_GAMMA;
> +                       if (green >= BDW_MAX_GAMMA)
> +                               green = BDW_MAX_GAMMA;
> +                       if (red >= BDW_MAX_GAMMA)
> +                               red = BDW_MAX_GAMMA;
> +
> +                       blue_fract = (blue >> 16) & 0xFF;
> +                       green_fract = (green >> 16) & 0xFF;
> +                       red_fract = (red >> 16) & 0xFF;
> +                       /* Red (23:16) Green (15:8) and Blue (7:0) */
> +                       word = red_fract << 16 ;
> +                       word = word | (green_fract << 8);
> +                       word = word | blue_fract;
> +                       gamma = INREG(offset);
> +                       if (gamma != word) {
> +                               igt_warn("Register Values not proper read value =%x \t  written = %x \t ", gamma, word);
> +                               return false;
> +                       }
> +                       offset += 4;
> +                       count++;
> +               }
> +               break;
> +       case GEN9_10BIT_GAMMA_MAX_VALS:
> +               count = 0;
> +               while (count < GEN9_10BIT_GAMMA_MAX_VALS) {
> +                       blue = gamma_lut[count].b32;
> +                       green = gamma_lut[count].g32;
> +                       red = gamma_lut[count].r32;
> +                       if (blue >= BDW_MAX_GAMMA)
> +                               blue = BDW_MAX_GAMMA;
> +                       if (green >= BDW_MAX_GAMMA)
> +                               green = BDW_MAX_GAMMA;
> +                       if (red >= BDW_MAX_GAMMA)
> +                               red = BDW_MAX_GAMMA;
> +
> +                       blue_fract = (blue >> 14) & 0x3FF ;
> +                       green_fract = (green >> 14) & 0x3FF;
> +                       red_fract = (red >> 14) & 0x3FF;
> +                       word = red_fract << 20;
> +                       word = word | (green_fract << 10);
> +                       word = word | blue_fract;
> +                       gamma = INREG(offset);
> +                       if (gamma != word) {
> +                               igt_warn("Register Values not proper read value =%x \t  written = %x \t ", gamma, word);
> +                               return false;
> +                       }
> +                       count++;
> +               }
> +               break;
> +       case GEN9_SPLITGAMMA_MAX_VALS:
> +               count = 0;
> +               while (count < GEN9_10BIT_GAMMA_MAX_VALS) {
> +                       blue = gamma_lut[count].b32;
> +                       green = gamma_lut[count].g32;
> +                       red = gamma_lut[count].r32;
> +                       if (blue >= BDW_MAX_GAMMA)
> +                               blue = BDW_MAX_GAMMA;
> +                       if (green >= BDW_MAX_GAMMA)
> +                               green = BDW_MAX_GAMMA;
> +                       if (red >= BDW_MAX_GAMMA)
> +                               red = BDW_MAX_GAMMA;
> +                       blue_fract = (blue >> 14) & 0x3FF ;
> +                       green_fract = (green >> 14) & 0x3FF;
> +                       red_fract = (red >> 14) & 0x3FF;
> +                       word = red_fract << 20;
> +                       word = word | (green_fract << 10);
> +                       word = word | blue_fract;
> +                       gamma = INREG(offset);
> +                       if (gamma != word) {
> +                               igt_warn("Register Values not proper read value =%x \t  written = %x \t ", gamma, word);
> +                               return false;
> +                       }
> +                       count++;
> +               }
> +               break;
> +
> +       case GEN9_12BIT_GAMMA_MAX_VALS:
> +               count = 0;
> +               even_word = 0x0;
> +               odd_word = 0x0;
> +               while (count < GEN9_12BIT_GAMMA_MAX_VALS - 1) {
> +                       blue = gamma_lut[count].b32;
> +                       green = gamma_lut[count].g32;
> +                       red = gamma_lut[count].r32;
> +                       if (blue >= BDW_MAX_GAMMA)
> +                               blue = BDW_MAX_GAMMA;
> +                       if (green >= BDW_MAX_GAMMA)
> +                               green = BDW_MAX_GAMMA;
> +                       if (red >= BDW_MAX_GAMMA)
> +                               red = BDW_MAX_GAMMA;
> +
> +                       red_fract = (red >> 8) & 0xFFFF ;
> +                       green_fract = (green >> 8) & 0xFFFF;
> +                       blue_fract = (blue >> 8) & 0xFFFF;
> +
> +                       red_fract1 = red_fract & 0x3F ;
> +                       green_fract1 = green_fract & 0x3F ;
> +                       blue_fract1 = blue_fract & 0x3F ;
> +                       even_word = red_fract1 << 24;
> +                       even_word = even_word | (green_fract1  << 14) ;
> +                       even_word = even_word | (blue_fract1  << 4);
> +                       even_word = even_word & 0xFF0FC3F0 ;
> +
> +                       gamma = INREG(offset);
> +                       if (gamma != even_word) {
> +                               igt_warn("EVEN:Register Values not proper read value =%x \t  written = %x \t count = %d ", gamma, even_word, count);
> +                               return false;
> +                       }
> +                       gamma = 0x0;
> +                       red_fract2 =  ((red_fract >> 6) & 0x3FF);
> +                       green_fract2 = ((green_fract >> 6) & 0x3FF);
> +                       blue_fract2 = ((blue_fract >> 6) & 0x3FF);
> +
> +                       odd_word = (red_fract2 << 20);
> +                       odd_word = odd_word | (green_fract2  << 10) ;
> +                       odd_word = odd_word | blue_fract2 ;
> +
> +                       gamma = INREG(offset);
> +
> +                       if (gamma != odd_word) {
> +                               igt_warn("ODD:Register Values not proper read value =%x \t  written = %x \t ", gamma, odd_word);
> +                               return false;
> +                       }
> +                       count++;
> +               }
> +               break;
> +       }
> +
> +       intel_register_access_fini();
> +
> +       igt_info("Gamma Values Are Programmed Correctly\n");
> +       return true;
> +}
> +static void test_pipe_degamma(struct data_t *data, igt_display_t *display, igt_output_t *output,
> +                       igt_plane_t *plane, uint32_t num_samples, int values, int pipe1)
> +{
> +       struct drm_palette *degamma_data =  NULL;
> +       int res, ret;
> +       float degamma;
> +       enum pipe pipe;
> +       enum igt_commit_style commit;
> +       int  i;
> +       int fb_id, fb_id1;
> +       int width, height;
> +       uint32_t pixelformat = DRM_FORMAT_XRGB8888;
> +       bool status = false;
> +       commit = COMMIT_UNIVERSAL;
> +
> +       int brightness = 50, contrast = 50, blob_length;
> +       if (values == GAMMA_1)
> +               degamma = 1.0;
> +       else if (values == GAMMA_2)
> +               degamma = 2.0;
> +       else
> +               degamma = 2.2;
> +       if (num_samples == 0)
> +               blob_length = 1;
> +       else
> +               blob_length = (sizeof(struct drm_palette) + (num_samples * sizeof(struct drm_r32g32b32)));
> +
> +       degamma_data = malloc(blob_length);
> +       struct drm_r32g32b32 degamma_ptr[num_samples];
> +       write_gamma_lut(brightness, contrast, degamma, num_samples, degamma_ptr);
> +       for (int i = 0; i < num_samples; i++)
> +               degamma_data->lut[i] = degamma_ptr[i];
> +       int blob_id = create_blob(display->drm_fd, (uint64_t *)(degamma_data), blob_length);
> +       if (blob_id < 0) {
> +               igt_warn("Set blob IOCTL failed\n");
> +       }
> +       igt_assert_lte(0, blob_id);
> +       res = set_color_property(display->drm_fd, output->config.crtc->crtc_id,
> +                       DRM_MODE_OBJECT_CRTC, "PALETTE_BEFORE_CTM", blob_id);
> +       ret = get_color_property(display->drm_fd, output->config.crtc->crtc_id,
> +                       DRM_MODE_OBJECT_CRTC, "PALETTE_BEFORE_CTM", blob_id);
> +       igt_assert_lte(0, res);
> +       igt_assert_lte(0, ret);
> +       enable_plane(data, display, output, pipe1);
> +       if (num_samples != 0) {
> +               status = gamma_register_validation(pipe1, num_samples, degamma_data->lut);
> +               free(degamma_data);
> +       }
> +       igt_assert(status);
> +
> +
> +}
> +
> +static void test_pipe_gamma(struct data_t *data, igt_display_t *display, igt_output_t *output,
> +               uint32_t num_samples, int values, int pipe1)
> +{
> +       enum igt_commit_style commit;
> +       int res, i;
> +       int fb_id, fb_id1;
> +       int width, height;
> +       igt_plane_t *plane;
> +       uint32_t pixelformat = DRM_FORMAT_XRGB8888;
> +       commit = COMMIT_UNIVERSAL;
> +       enum pipe pipe;
> +       struct drm_palette *gamma_data =  NULL;
> +       int  ret;
> +       bool status = false;
> +       float gamma;
> +       int brightness = 50, contrast = 50, blob_length;
> +       if (values == GAMMA_1)
> +               gamma = 1.0;
> +       else if (values == GAMMA_2)
> +               gamma = 2.0;
> +       else if (values == GAMMA_2_2)
> +               gamma = 2.2;
> +       else
> +               gamma = values;
> +       if (num_samples == 0)
> +               blob_length = 1;
> +       else
> +               blob_length = (sizeof(struct drm_palette) + (num_samples * sizeof(struct drm_r32g32b32)));
> +
> +       gamma_data = malloc(blob_length);
> +       struct drm_r32g32b32 gamma_ptr[num_samples];
> +       write_gamma_lut(brightness, contrast, gamma, num_samples, gamma_ptr);
> +
> +       for (int i = 0; i < num_samples; i++)
> +               gamma_data->lut[i] = gamma_ptr[i];
> +
> +
> +       int blob_id = create_blob(display->drm_fd, (uint64_t *)(gamma_data), blob_length);
> +       if (blob_id < 0) {
> +               igt_warn("Set blob IOCTL failed\n");
> +       }
> +       igt_assert_lte(0, blob_id);
> +
> +
> +       res = set_color_property(display->drm_fd, output->config.crtc->crtc_id,
> +                       DRM_MODE_OBJECT_CRTC, "PALETTE_AFTER_CTM", blob_id);
> +       if (res < 0) {
> +               igt_info("Setting Gamma failed!");
> +
> +               free(gamma_data);
> +       }
> +       igt_assert_lte(0, res);
> +
> +       ret = get_color_property(display->drm_fd, output->config.crtc->crtc_id,
> +                       DRM_MODE_OBJECT_CRTC, "PALETTE_AFTER_CTM", blob_id);
> +       if (ret < 0) {
> +               igt_info("Getting Gamma failed!");
> +               free(gamma_data);
> +       }
> +       igt_assert_lte(0, ret);
> +       enable_plane(data, display, output, pipe1);
> +       if (num_samples != 0) {
> +
> +               status = gamma_register_validation(pipe1, num_samples, gamma_data->lut);
> +
> +               igt_assert(status);
> +       }
> +
> +       free(gamma_data);
> +}
> +static void test_pipe_color(struct data_t *data, char *prop_name, int enable, int display_in, int value)
> +{
> +       igt_display_t *display = &data->display;
> +       igt_output_t *output;
> +       igt_plane_t *plane;
> +       enum pipe pipe;
> +       enum igt_commit_style commit;
> +       int res, i;
> +       int fb_id, fb_id1;
> +       int width, height;
> +       uint32_t pixelformat = DRM_FORMAT_XRGB8888;
> +       commit = COMMIT_UNIVERSAL;
> +       for_each_connected_output(display, output) {
> +               drmModeModeInfo *mode;
> +               pipe = output->config.pipe;
> +               if (display_in != 2 && pipe != display_in)
> +                               break;
> +               igt_plane_t *plane;
> +               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);
> +               /*Random sized Frame buffer creation */
> +               width = 600;
> +               height = 600;
> +
> +               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,
> +                               0.0,
> +                               1.0,
> +                               0.0,
> +                               &data->fb);
> +               plane->crtc_x = 100;
> +               plane->crtc_y = 100;
> +               plane->fb_changed = true;
> +               igt_plane_set_fb(plane, &data->fb);
> +               igt_display_commit2(display, commit);
> +
> +               if ((strcmp(prop_name, "gamma_property_8bit") == 0) &&
> +                               enable == ENABLE){
> +                       test_pipe_gamma(data, display, output,
> +                                       GEN9_8BIT_GAMMA_MAX_VALS, value, pipe);
> +               } else  if ((strcmp(prop_name, "gamma_property_8bit") == 0) &&
> +                               enable == DISABLE) {
> +                       test_pipe_gamma(data, display, output,  0, value, pipe);
> +               } else  if ((strcmp(prop_name, "gamma_property_10bit") == 0) &&
> +                               enable == ENABLE) {
> +                       test_pipe_gamma(data, display, output, GEN9_10BIT_GAMMA_MAX_VALS, value, pipe);
> +               } else  if ((strcmp(prop_name, "csc_property") == 0)) {
> +                       test_pipe_csc(data, display, output, plane, enable, value, pipe);
> +               } else  if ((strcmp(prop_name, "degamma_property") == 0) &&
> +                               enable == ENABLE) {
> +                       test_pipe_degamma(data, display, output, plane, GEN9_SPLITGAMMA_MAX_VALS, value, pipe);
> +               } else  if ((strcmp(prop_name, "degamma_property") == 0) &&
> +                       enable == DISABLE) {
> +                       test_pipe_degamma(data, display, output, plane, 0, value, pipe);
> +               } else  if ((strcmp(prop_name, "gamma_property_split") == 0) &&
> +                               enable == ENABLE) {
> +                       test_pipe_gamma(data, display, output,
> +                                       GEN9_SPLITGAMMA_MAX_VALS, value, pipe);
> +               } else  if ((strcmp(prop_name, "gamma_property_12bit") == 0) && enable == ENABLE) {
> +                       test_pipe_gamma(data, display, output,
> +                                       GEN9_12BIT_GAMMA_MAX_VALS, value, pipe);
> +
> +               } else {
> +                       igt_info("Invalid Test\n");
> +               }
> +
> +               cleanup_fb(data);
> +               plane = igt_output_get_plane(output, IGT_PLANE_2);
> +               usleep(2000000);

Is this sleep necassary?


> +               cleanup_crtc(data, output, plane);
> +
> +       }
> +}
> +
> +static void print_usage(void)
> +{
> +       igt_info("Usage: ./kms_color \n");
> +       igt_info("\t-d\t<display>           \t0->primary\t1->Secondary \n");
> +       igt_info("\t-t\t<test>              \t0->csc    \t1->gamma\t2->degamma\n");
> +       igt_info("\t-e\t<enable/disable>    \t0->enable \t1->disable\n");
> +       igt_info("\t-v\t<Values>            \tFor csc values:  \t0->Red \t1->Green\t2->Blue \t3->Unity \n");
> +       igt_info("                          \tFor Gamma values:\t0->1.0 \t1->2.0  \t2->2.2  \tx-> Any Gamma Custom Values\n");
> +       igt_info("\t-m\t<Mode>              \tOnly For Gamma   \t0->8bit\t1->10bit\t2->12bit\t3->SplitLevel\n");
> +}
> +
> +main(int argc, char *argv[])
> +{
> +       struct data_t data = {};
> +       int gen = 0;
> +       int display_id = 0;
> +       int option = 0, count = -1;
> +       int display = -1, test = -1, values = -1, enable_in = -1, mode = 0;
> +       while ((option = getopt(argc, argv, "d:t:e:v:m:")) != -1) {

Please use igt_subtest_init_parse_opts to add extra options to a test
as this allows the standard command line options (such as
--list-subtests) to continue working.


> +               switch (option) {
> +               case 'd':
> +                        display = atoi(optarg);
> +                        break;
> +               case 't':
> +                        test = atoi(optarg);
> +                        break;
> +               case 'v':
> +                        values = atoi(optarg);
> +                        break;
> +               case 'e':
> +                        enable_in = atoi(optarg);
> +                        break;
> +               case 'm':
> +                        mode = atoi(optarg);
> +                        break;
> +               default:
> +                        print_usage();
> +                        return -1;
> +               }
> +       }
> +       count =  argc;
> +       igt_skip_on_simulation();
> +       igt_subtest_init(argc, argv);
> +       igt_fixture{
> +               data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
> +               kmstest_set_vt_graphics_mode();
> +               igt_display_init(&data.display, data.drm_fd);
> +               data.gen = intel_gen(intel_get_drm_devid(data.drm_fd));
> +       }
> +       igt_require(data.gen >= 9);

data.gen is only set inside the igt_fixture block, so may not be
available outside it. Therefore, this check needs to be inside the
igt_fixture block above.


> +       if (count == 1) {
> +       igt_info("Color Generic Tests\n");

Missing indentation here.


> +       display = 2;
> +       values = 1;
> +       igt_subtest_f("Enable_Gamma_8bit")

Subtest names are generally lower case with words separated by
hyphens. Also, since there is no format argument, igt_subtest would be
sufficient.


> +               test_pipe_color(&data, "gamma_property_8bit", ENABLE, display, values);
> +       igt_subtest_f("Enable_Gamma_10bit")
> +               test_pipe_color(&data, "gamma_property_10bit", ENABLE, display, values);
> +       igt_subtest_f("Enable_Gamma_12bit")
> +               test_pipe_color(&data, "gamma_property_12bit", ENABLE, display, values);
> +       igt_subtest_f("Enable_SPLIT_GAMMA")
> +               test_pipe_color(&data, "gamma_property_split", ENABLE, display, values);
> +       igt_subtest_f("Disable_Gamma_8bit")
> +               test_pipe_color(&data, "gamma_property_8bit", DISABLE, display, values);
> +       igt_subtest_f("CSC_ENABLE")
> +               test_pipe_color(&data, "csc_property", ENABLE, display, values);
> +       igt_subtest_f("CSC_DISABLE")
> +               test_pipe_color(&data, "csc_property", ENABLE, display, values);
> +       igt_subtest_f("Enable_De-gamma")
> +               test_pipe_color(&data, "degamma_property", ENABLE, display, values);
> +       igt_subtest_f("Disable_De-gamma")
> +               test_pipe_color(&data, "degamma_property", DISABLE, display, values);
> +       } else {
> +               if (((count < 7) || (display == -1) || (test == -1) || (values == -1) || (enable_in == -1))) {
> +                       print_usage();
> +                       return -1;
> +               } else {
> +                       igt_info("Color Customised Tests\n");
> +
> +                       if (test == CSC_TEST) {

The followng subtests are repeated from above. Specifying a specific
subtest should be possible using the --run-subtest option, so I don't
think the other options to specify a test here are required.


> +                               igt_subtest_f("CSC")
> +                                       test_pipe_color(&data, "csc_property", enable_in, display, values);
> +                       } else if (test == GAMMA_TEST) {
> +                               if (enable_in == ENABLE) {
> +                                       if (mode == 0) {
> +                                               igt_subtest_f("Enable_Gamma_8bit")
> +                                                       test_pipe_color(&data, "gamma_property_8bit", ENABLE, display, values);
> +                                       } else if (mode == 1) {
> +                                               igt_subtest_f("Enable_Gamma_10bit")
> +                                                       test_pipe_color(&data, "gamma_property_10bit", ENABLE, display, values);
> +
> +                                       } else if (mode == 2) {
> +                                               igt_subtest_f("Enable_Gamma_12bit")
> +                                                       test_pipe_color(&data, "gamma_property_12bit", ENABLE, display, values);
> +
> +                                       } else if (mode == 3) {
> +                                               igt_subtest_f("Enable_SPLIT_GAMMA")
> +                                                       test_pipe_color(&data, "gamma_property_split", ENABLE, display, values);
> +                                       }
> +                               } else {
> +                                       igt_subtest_f("Disable_Gamma_8bit")
> +                                               test_pipe_color(&data, "gamma_property_8bit", DISABLE, display, values);
> +
> +                               }
> +                       } else if (test == DEGAMMA_TEST) {
> +                               if (enable_in == ENABLE) {
> +                                       igt_subtest_f("Enable_De-gamma")
> +                                               test_pipe_color(&data, "degamma_property", ENABLE, display, values);
> +                               } else {
> +                                       igt_subtest_f("Disable_De-gamma")
> +                                               test_pipe_color(&data, "degamma_property", DISABLE, display, values);
> +
> +                               } } else {
> +                                       print_usage();
> +                               }
> +               }
> +
> +       }
> +       igt_fixture{
> +               igt_display_fini(&data.display);
> +       }
> +       igt_exit();
> +}
> +
> --
> 1.9.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx


More information about the Intel-gfx mailing list