From: Harry Wentland harry.wentland@amd.com Sent: Friday, November 26, 2021 10:25 PM To: Modem, Bhanuprakash bhanuprakash.modem@intel.com; igt- dev@lists.freedesktop.org; dri-devel@lists.freedesktop.org Cc: Kumar, Mukunda Pramodh mukunda.pramodh.kumar@intel.com; Ville Syrjälä ville.syrjala@linux.intel.com; Juha-Pekka Heikkila juhapekka.heikkila@gmail.com; Shankar, Uma uma.shankar@intel.com 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@intel.com
Add helper functions to support logarithmic gamma mode
Cc: Harry Wentland harry.wentland@amd.com Cc: Ville Syrjälä ville.syrjala@linux.intel.com Cc: Juha-Pekka Heikkila juhapekka.heikkila@gmail.com Cc: Uma Shankar uma.shankar@intel.com Signed-off-by: Mukunda Pramodh Kumar mukunda.pramodh.kumar@intel.com Signed-off-by: Bhanuprakash Modem bhanuprakash.modem@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)
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,