> From: Harry Wentland <harry.wentland@xxxxxxx> > Sent: Friday, November 26, 2021 10:25 PM > To: Modem, Bhanuprakash <bhanuprakash.modem@xxxxxxxxx>; igt- > dev@xxxxxxxxxxxxxxxxxxxxx; dri-devel@xxxxxxxxxxxxxxxxxxxxx > Cc: Kumar, Mukunda Pramodh <mukunda.pramodh.kumar@xxxxxxxxx>; Ville Syrjälä > <ville.syrjala@xxxxxxxxxxxxxxx>; Juha-Pekka Heikkila > <juhapekka.heikkila@xxxxxxxxx>; Shankar, Uma <uma.shankar@xxxxxxxxx> > Subject: Re: [i-g-t 12/14] kms_color_helper: Add helper functions to support > logarithmic gamma mode > > On 2021-11-15 04:47, Bhanuprakash Modem wrote: > > From: Mukunda Pramodh Kumar <mukunda.pramodh.kumar@xxxxxxxxx> > > > > Add helper functions to support logarithmic gamma mode > > > > Cc: Harry Wentland <harry.wentland@xxxxxxx> > > Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > Cc: Juha-Pekka Heikkila <juhapekka.heikkila@xxxxxxxxx> > > Cc: Uma Shankar <uma.shankar@xxxxxxxxx> > > Signed-off-by: Mukunda Pramodh Kumar <mukunda.pramodh.kumar@xxxxxxxxx> > > Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem@xxxxxxxxx> > > --- > > 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) > > How does this create a logarithmic LUT? It seems to do the same > as coeffs_to_lut (which is also full of intellisms) except that > it also scales the values by max_hw_value / max_segment_value for > reasons that are not obvious to me. Yes, this is just an another version of coeffs_to_lut, I'll float a new rev with this change. > > > +{ > > + struct drm_color_lut *lut; > > + int i, lut_size = gamma->size; > > + /* This is the maximum value due to 16 bit precision in hardware. */ > > + uint32_t max_hw_value = (1 << 16) - 1; > > + unsigned int max_segment_value = 1 << 24; > > + > > > This looks like it is specific to Intel HW. Intel-specific things should > not live in kms_ tests. > > Shouldn't these be encoded in the drm_color_lut_range definitions? > > To be honest I am not clear why max_hw_value and max_segment_value > differ here. 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. */ > > Harry > > > + 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) > > +{ > > + 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; > > 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); > > + 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); > > + free(gamma_log); > > + free(lut); > > + clear_segment_data(segment_info); > > + drmModeFreeProperty(gamma_mode); > > +} > > + > > 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, > >