> From: Pekka Paalanen <ppaala...@gmail.com>
> Sent: Thursday, November 18, 2021 3:15 PM
> To: Modem, Bhanuprakash <bhanuprakash.mo...@intel.com>
> Cc: igt-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; Kumar,
> Mukunda Pramodh <mukunda.pramodh.ku...@intel.com>; Juha-Pekka Heikkila
> <juhapekka.heikk...@gmail.com>; Shankar, Uma <uma.shan...@intel.com>
> Subject: Re: [i-g-t 12/14] kms_color_helper: Add helper functions to support
> logarithmic gamma mode
> 
> On Mon, 15 Nov 2021 15:17:57 +0530
> Bhanuprakash Modem <bhanuprakash.mo...@intel.com> wrote:
> 
> > From: Mukunda Pramodh Kumar <mukunda.pramodh.ku...@intel.com>
> >
> > Add helper functions to support logarithmic gamma mode
> >
> > Cc: Harry Wentland <harry.wentl...@amd.com>
> > Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
> > Cc: Juha-Pekka Heikkila <juhapekka.heikk...@gmail.com>
> > Cc: Uma Shankar <uma.shan...@intel.com>
> > Signed-off-by: Mukunda Pramodh Kumar <mukunda.pramodh.ku...@intel.com>
> > Signed-off-by: Bhanuprakash Modem <bhanuprakash.mo...@intel.com>
> > ---
> >  tests/kms_color_helper.c | 127 +++++++++++++++++++++++++++++++++++++++
> >  tests/kms_color_helper.h |  16 +++++
> >  2 files changed, 143 insertions(+)
> >
> > diff --git a/tests/kms_color_helper.c b/tests/kms_color_helper.c
> > index c65b7a0f50..7ea8282df3 100644
> > --- a/tests/kms_color_helper.c
> > +++ b/tests/kms_color_helper.c
> > @@ -190,6 +190,33 @@ struct drm_color_lut *coeffs_to_lut(data_t *data,
> >     return lut;
> >  }
> >
> > +struct drm_color_lut *coeffs_to_logarithmic_lut(data_t *data,
> > +                                           const gamma_lut_t *gamma,
> > +                                           uint32_t color_depth,
> > +                                           int off)
> > +{
> > +   struct drm_color_lut *lut;
> > +   int i, lut_size = gamma->size;
> > +   /* This is the maximum value due to 16 bit precision in hardware. */
> 
> In whose hardware?
> 
> Are igt tests not supposed to be generic for everything that exposes
> the particular KMS properties?
> 
> This also hints that the UAPI design is lacking, because userspace
> needs to know hardware specific things out of thin air. Display servers
> are not going to have hardware-specific code. They specialise based on
> the existence of KMS properties instead.

Yeah, the comment is misleading and variable names also bit confusing.

As uapi supports U0.16 precision the max supported value would be (1 << 16) - 1
and Intel h/w supports max value of (1 << 24) so we need to scale the values
accordingly.

So, need to drop h/w specific hardcoded stuff and read from uapi & rename the
variables as below:

max_uapi_value = (1 << 16) - 1;
max_hw_value = /* Read from the uapi. */

> 
> > +   uint32_t max_hw_value = (1 << 16) - 1;
> > +   unsigned int max_segment_value = 1 << 24;
> > +
> > +   lut = malloc(sizeof(struct drm_color_lut) * lut_size);
> > +
> > +   for (i = 0; i < lut_size; i++) {
> > +           double scaling_factor = (double)max_hw_value /
> (double)max_segment_value;
> > +           uint32_t r = MIN((gamma->coeffs[i].r * scaling_factor),
> max_hw_value);
> > +           uint32_t g = MIN((gamma->coeffs[i].g * scaling_factor),
> max_hw_value);
> > +           uint32_t b = MIN((gamma->coeffs[i].b * scaling_factor),
> max_hw_value);
> > +
> > +           lut[i].red = r;
> > +           lut[i].green = g;
> > +           lut[i].blue = b;
> > +   }
> > +
> > +   return lut;
> > +}
> > +
> >  void set_degamma(data_t *data,
> >              igt_pipe_t *pipe,
> >              const gamma_lut_t *gamma)
> > @@ -203,6 +230,15 @@ void set_degamma(data_t *data,
> >     free(lut);
> >  }
> >
> > +void set_pipe_gamma(igt_pipe_t *pipe,
> > +               uint64_t value,
> > +               struct drm_color_lut *lut,
> > +               uint32_t size)
> > +{
> > +   igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_GAMMA_MODE, value);
> > +   igt_pipe_obj_replace_prop_blob(pipe, IGT_CRTC_GAMMA_LUT, lut, size);
> > +}
> > +
> >  void set_gamma(data_t *data,
> >            igt_pipe_t *pipe, const gamma_lut_t *gamma)
> >  {
> > @@ -241,6 +277,51 @@ void disable_prop(igt_pipe_t *pipe, enum
> igt_atomic_crtc_properties prop)
> >             igt_pipe_obj_replace_prop_blob(pipe, prop, NULL, 0);
> >  }
> >
> > +drmModePropertyPtr get_pipe_gamma_degamma_mode(igt_pipe_t *pipe,
> > +                                          enum igt_atomic_crtc_properties 
> > prop)
> > +{
> > +   igt_display_t *display = pipe->display;
> > +   uint32_t prop_id = pipe->props[prop];
> > +   drmModePropertyPtr drmProp;
> > +
> > +   igt_assert(prop_id);
> > +
> > +   drmProp = drmModeGetProperty(display->drm_fd, prop_id);
> > +
> > +   igt_assert(drmProp);
> > +   igt_assert(drmProp->count_enums);
> > +
> > +   return drmProp;
> > +}
> > +
> > +gamma_lut_t *pipe_create_linear_lut(segment_data_t *info)
> 
> Identity transformation?
> 
> > +{
> > +   uint32_t segment, entry, index = 0;
> > +   double val;
> > +   int i = 0;
> > +   gamma_lut_t *gamma = alloc_lut(info->entries_count);
> > +
> > +   igt_assert(gamma);
> > +
> > +   gamma->size = info->entries_count;
> > +   for (segment = 0; segment < info->segment_count; segment++) {
> > +           uint32_t entry_count = info->segment_data[segment].count;
> > +           uint32_t start = (segment == 0) ? 0 : (1 << (segment - 1));
> > +           uint32_t end = 1 << segment;
> > +
> > +           for (entry = 0; entry < entry_count; entry++) {
> > +                   val = (index == 0) ? /* First entry is Zero. */
> > +                           0 : start + entry *
> > +                           ((end - start) * 1.0 / entry_count);
> > +
> > +                   set_rgb(&gamma->coeffs[i++], val);
> > +                   index++;
> > +           }
> > +   }
> > +
> > +   return gamma;
> > +}
> > +
> >  drmModePropertyPtr get_plane_gamma_degamma_mode(igt_plane_t *plane,
> >                             enum igt_atomic_plane_properties prop)
> >  {
> > @@ -331,6 +412,7 @@ segment_data_t *get_segment_data(data_t *data,
> >     info->segment_data = malloc(sizeof(struct drm_color_lut_range) * info-
> >segment_count);
> >     igt_assert(info->segment_data);
> >
> > +   info->entries_count = 0;
> 
> What's this?
> 
> >     for (i = 0; i < info->segment_count; i++) {
> >             info->entries_count += lut_range[i].count;
> >             info->segment_data[i] = lut_range[i];
> > @@ -341,6 +423,51 @@ segment_data_t *get_segment_data(data_t *data,
> >     return info;
> >  }
> >
> > +void set_advance_gamma(data_t *data, igt_pipe_t *pipe, enum gamma_type
> type)
> > +{
> > +   igt_display_t *display = &data->display;
> > +   gamma_lut_t *gamma_log;
> > +   drmModePropertyPtr gamma_mode = NULL;
> > +   segment_data_t *segment_info = NULL;
> > +   struct drm_color_lut *lut = NULL;
> > +   int lut_size = 0;
> > +
> > +   drmSetClientCap(data->drm_fd, DRM_CLIENT_CAP_ADVANCE_GAMMA_MODES, 1);
> 
> Is this how we are going to do cross-software DRM-master hand-over or
> switching compatibility in general?
> 
> Add a new client cap for every new KMS property, and if the KMS client
> does not set the property, the kernel will magically reset it to ensure
> the client's expectations are met? Is that how it works?
> 
> Or why does this exist?

Very good point. Need to explore on this.
I think the expectation is: Whoever sets this property should clear before
hand-over or switching the compatibility.

> 
> > +   gamma_mode = get_pipe_gamma_degamma_mode(pipe, IGT_CRTC_GAMMA_MODE);
> > +
> > +   for (int i = 0; i < gamma_mode->count_enums; i++) {
> > +           if (!strcmp(gamma_mode->enums[i].name, "logarithmic gamma")) {
> > +                   segment_info = get_segment_data(data,
> > +                                                   
> > gamma_mode->enums[i].value,
> > +                                                   
> > gamma_mode->enums[i].name);
> > +                   lut_size = sizeof(struct drm_color_lut) *
> > +                                     segment_info->entries_count;
> > +                   if (type == LINEAR_GAMMA) {
> > +                           gamma_log = 
> > pipe_create_linear_lut(segment_info);
> > +                           lut = coeffs_to_logarithmic_lut(data,
> > +                                                           gamma_log,
> > +                                                           
> > data->color_depth,
> > +                                                           0);
> > +                   } else if (type == MAX_GAMMA) {
> > +                           gamma_log = generate_table_max(segment_info-
> >entries_count);
> > +                           gamma_log->size = segment_info->entries_count;
> > +                           lut = coeffs_to_lut(data, gamma_log,
> > +                                               data->color_depth, 0);
> > +                   }
> > +                   set_pipe_gamma(pipe, gamma_mode->enums[i].value,
> > +                                  lut, lut_size);
> > +                   igt_display_commit2(display, display->is_atomic
> > +                                       ? COMMIT_ATOMIC : COMMIT_LEGACY);
> > +                   break;
> > +           }
> > +   }
> > +   drmSetClientCap(data->drm_fd, DRM_CLIENT_CAP_ADVANCE_GAMMA_MODES, 0);
> 
> I've never seen this done before. I did not know client caps could be
> reset.
> 
> > +   free(gamma_log);
> > +   free(lut);
> > +   clear_segment_data(segment_info);
> > +   drmModeFreeProperty(gamma_mode);
> > +}
> 
> 
> Thanks,
> pq
> 
> > +
> >  void set_plane_gamma(igt_plane_t *plane,
> >             char *mode,
> >             struct drm_color_lut_ext *lut,
> > diff --git a/tests/kms_color_helper.h b/tests/kms_color_helper.h
> > index 5a35dcaac1..c863874f0c 100644
> > --- a/tests/kms_color_helper.h
> > +++ b/tests/kms_color_helper.h
> > @@ -70,6 +70,11 @@ typedef struct {
> >     uint32_t entries_count;
> >  } segment_data_t;
> >
> > +enum gamma_type {
> > +   LINEAR_GAMMA,
> > +   MAX_GAMMA
> > +};
> > +
> >  #define MIN(a, b) ((a) < (b) ? (a) : (b))
> >
> >  void paint_gradient_rectangles(data_t *data,
> > @@ -89,6 +94,10 @@ struct drm_color_lut *coeffs_to_lut(data_t *data,
> >                                 const gamma_lut_t *gamma,
> >                                 uint32_t color_depth,
> >                                 int off);
> > +struct drm_color_lut *coeffs_to_logarithmic_lut(data_t *data,
> > +                                           const gamma_lut_t *gamma,
> > +                                           uint32_t color_depth,
> > +                                           int off);
> >  void set_degamma(data_t *data,
> >              igt_pipe_t *pipe,
> >              const gamma_lut_t *gamma);
> > @@ -98,12 +107,19 @@ void set_gamma(data_t *data,
> >  void set_ctm(igt_pipe_t *pipe, const double *coefficients);
> >  void disable_prop(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop);
> >
> > +drmModePropertyPtr get_pipe_gamma_degamma_mode(igt_pipe_t *pipe,
> > +                                          enum igt_atomic_crtc_properties
> > +                                          prop);
> >  drmModePropertyPtr get_plane_gamma_degamma_mode(igt_plane_t *plane,
> >     enum igt_atomic_plane_properties prop);
> >  void clear_segment_data(segment_data_t *info);
> > +gamma_lut_t *pipe_create_linear_lut(segment_data_t *info);
> >  struct drm_color_lut_ext *create_linear_lut(segment_data_t *info);
> >  struct drm_color_lut_ext *create_max_lut(segment_data_t *info);
> >  segment_data_t *get_segment_data(data_t *data, uint64_t blob_id, char
> *mode);
> > +void set_pipe_gamma(igt_pipe_t *pipe, uint64_t value,
> > +               struct drm_color_lut *lut, uint32_t size);
> > +void set_advance_gamma(data_t *data, igt_pipe_t *pipe, enum gamma_type
> type);
> >  void set_plane_gamma(igt_plane_t *plane,
> >     char *mode, struct drm_color_lut_ext *lut, uint32_t size);
> >  void set_plane_degamma(igt_plane_t *plane,

Reply via email to