Message ID | 1433938032-20240-1-git-send-email-dhanya.p.r@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, 10 Jun 2015, Dhanya Pillai <dhanya.p.r@intel.com> wrote: > From: root <root@pvishwak-ubuntu.iind.intel.com> Try 'git commit --amend --reset-author' on that commit. BR, Jani. > > Signed-off-by: dhanyapr <dhanya.p.r@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.9.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
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); + } +} +