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