[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