backend/native: Port gamma management to Atomic KMS API

As a side note: fun things happen when gamma is set wrong!
This commit is contained in:
Georges Basile Stavracas Neto 2019-06-19 20:39:29 -03:00
parent 6f436023ed
commit cf9136ecd6
No known key found for this signature in database
GPG Key ID: 886C17EE170D1385
7 changed files with 249 additions and 88 deletions

View File

@ -69,6 +69,10 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc,
MetaKmsImplDevice *impl_device,
drmModeCrtc *drm_crtc)
{
g_clear_pointer (&crtc->current_state.gamma.red, g_free);
g_clear_pointer (&crtc->current_state.gamma.green, g_free);
g_clear_pointer (&crtc->current_state.gamma.blue, g_free);
crtc->current_state = (MetaKmsCrtcState) {
.rect = {
.x = drm_crtc->x,
@ -78,7 +82,20 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc,
},
.is_drm_mode_valid = drm_crtc->mode_valid,
.drm_mode = drm_crtc->mode,
.gamma = {
.size = drm_crtc->gamma_size,
.red = g_new0 (unsigned short, drm_crtc->gamma_size),
.green = g_new0 (unsigned short, drm_crtc->gamma_size),
.blue = g_new0 (unsigned short, drm_crtc->gamma_size),
},
};
drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device),
crtc->id,
drm_crtc->gamma_size,
crtc->current_state.gamma.red,
crtc->current_state.gamma.green,
crtc->current_state.gamma.blue);
}
void
@ -118,3 +135,26 @@ static void
meta_kms_crtc_class_init (MetaKmsCrtcClass *klass)
{
}
void
meta_kms_crtc_get_gamma (MetaKmsCrtc *crtc,
gsize *size,
unsigned short **red,
unsigned short **green,
unsigned short **blue)
{
unsigned int n_gamma_values = crtc->current_state.gamma.size;
unsigned int i;
*size = n_gamma_values;
*red = g_new0 (unsigned short, n_gamma_values);
*green = g_new0 (unsigned short, n_gamma_values);
*blue = g_new0 (unsigned short, n_gamma_values);
for (i = 0; i < n_gamma_values; i++)
{
*red[i] = crtc->current_state.gamma.red[i];
*green[i] = crtc->current_state.gamma.green[i];
*blue[i] = crtc->current_state.gamma.blue[i];
}
}

View File

@ -36,6 +36,13 @@ typedef struct _MetaKmsCrtcState
uint32_t common_possible_crtcs;
uint32_t common_possible_clones;
uint32_t encoder_device_idxs;
struct {
unsigned int size;
unsigned short *red;
unsigned short *green;
unsigned short *blue;
} gamma;
} MetaKmsCrtcState;
#define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ())
@ -51,4 +58,10 @@ uint32_t meta_kms_crtc_get_id (MetaKmsCrtc *crtc);
int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc);
void meta_kms_crtc_get_gamma (MetaKmsCrtc *crtc,
gsize *size,
unsigned short **red,
unsigned short **green,
unsigned short **blue);
#endif /* META_KMS_CRTC_H */

View File

@ -62,6 +62,68 @@ G_DEFINE_TYPE (MetaKmsImplSimple, meta_kms_impl_simple,
static void
flush_postponed_page_flip_datas (MetaKmsImplSimple *impl_simple);
static char *
generate_gamma_ramp_string (size_t size,
unsigned short *red,
unsigned short *green,
unsigned short *blue)
{
GString *string;
int color;
string = g_string_new ("[");
for (color = 0; color < 3; color++)
{
unsigned short **color_ptr;
char color_char;
size_t i;
switch (color)
{
case 0:
color_ptr = &red;
color_char = 'r';
break;
case 1:
color_ptr = &green;
color_char = 'g';
break;
case 2:
color_ptr = &blue;
color_char = 'b';
break;
}
g_string_append_printf (string, " %c: ", color_char);
for (i = 0; i < MIN (4, size); i++)
{
int j;
if (size > 4)
{
if (i == 2)
g_string_append (string, ",...");
if (i >= 2)
j = i + (size - 4);
else
j = i;
}
else
{
j = i;
}
g_string_append_printf (string, "%s%hu",
j == 0 ? "" : ",",
(*color_ptr)[i]);
}
}
g_string_append (string, " ]");
return g_string_free (string, FALSE);
}
MetaKmsImplSimple *
meta_kms_impl_simple_new (MetaKms *kms,
GError **error)
@ -103,6 +165,46 @@ process_connector_property (MetaKmsImpl *impl,
return TRUE;
}
static gboolean
process_crtc_gamma (MetaKmsImpl *impl,
MetaKmsUpdate *update,
MetaKmsCrtcGamma *crtc_gamma,
GError **error)
{
MetaKmsCrtc *crtc = crtc_gamma->crtc;
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc);
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
g_autofree char *gamma_ramp_string = NULL;
uint32_t crtc_id;
int fd;
int ret;
fd = meta_kms_impl_device_get_fd (impl_device);
crtc_id = meta_kms_crtc_get_id (crtc);
gamma_ramp_string = generate_gamma_ramp_string (crtc_gamma->size,
crtc_gamma->red,
crtc_gamma->green,
crtc_gamma->blue);
g_debug ("Setting CRTC (%u) gamma to %s", crtc_id, gamma_ramp_string);
ret = drmModeCrtcSetGamma (fd,
crtc_id,
crtc_gamma->size,
crtc_gamma->red,
crtc_gamma->green,
crtc_gamma->blue);
if (ret != 0)
{
g_warning ("Failed to set CRTC (%u) Gamma: %s",
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
return FALSE;
}
return TRUE;
}
static gboolean
process_plane_property (MetaKmsImpl *impl,
MetaKmsPlane *plane,
@ -700,6 +802,14 @@ meta_kms_impl_simple_process_update (MetaKmsImpl *impl,
goto discard_page_flips;
}
for (l = meta_kms_update_get_crtc_gammas (update); l; l = l->next)
{
MetaKmsCrtcGamma *crtc_gamma = l->data;
if (!process_crtc_gamma (impl, update, crtc_gamma, error))
goto discard_page_flips;
}
for (l = meta_kms_update_get_mode_sets (update); l; l = l->next)
{
MetaKmsModeSet *mode_set = l->data;

View File

@ -67,6 +67,15 @@ typedef struct _MetaKmsPageFlip
gpointer custom_page_flip_user_data;
} MetaKmsPageFlip;
typedef struct _MetaKmsCrtcGamma
{
MetaKmsCrtc *crtc;
gsize size;
unsigned short *red;
unsigned short *green;
unsigned short *blue;
} MetaKmsCrtcGamma;
void meta_kms_update_set_connector_property (MetaKmsUpdate *update,
MetaKmsConnector *connector,
uint32_t prop_id,
@ -84,6 +93,8 @@ GList * meta_kms_update_get_page_flips (MetaKmsUpdate *update);
GList * meta_kms_update_get_connector_properties (MetaKmsUpdate *update);
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
gboolean meta_kms_update_has_mode_set (MetaKmsUpdate *update);
#endif /* META_KMS_UPDATE_PRIVATE_H */

View File

@ -32,6 +32,7 @@ struct _MetaKmsUpdate
GList *plane_assignments;
GList *page_flips;
GList *connector_properties;
GList *crtc_gammas;
};
static MetaKmsProperty *
@ -71,6 +72,30 @@ meta_kms_mode_set_free (MetaKmsModeSet *mode_set)
g_free (mode_set);
}
static void
meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *crtc_gamma)
{
g_free (crtc_gamma->red);
g_free (crtc_gamma->green);
g_free (crtc_gamma->blue);
g_free (crtc_gamma);
}
static unsigned short *
copy_unsigned_short_array (unsigned short *values,
gsize n_values)
{
unsigned short *copy;
if (!values)
return NULL;
copy = g_new (unsigned short, n_values);
memcpy (copy, values, sizeof (unsigned short) * n_values);
return copy;
}
MetaKmsPlaneAssignment *
meta_kms_update_assign_plane (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
@ -96,6 +121,28 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update,
return plane_assignment;
}
void
meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
gsize size,
unsigned short *red,
unsigned short *green,
unsigned short *blue)
{
MetaKmsCrtcGamma *crtc_gamma;
crtc_gamma = g_new0 (MetaKmsCrtcGamma, 1);
*crtc_gamma = (MetaKmsCrtcGamma) {
.crtc = crtc,
.size = size,
.red = copy_unsigned_short_array (red, size),
.green = copy_unsigned_short_array (green, size),
.blue = copy_unsigned_short_array (blue, size),
};
update->crtc_gammas = g_list_prepend (update->crtc_gammas, crtc_gamma);
}
void
meta_kms_update_mode_set (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
@ -210,6 +257,12 @@ meta_kms_update_get_connector_properties (MetaKmsUpdate *update)
return update->connector_properties;
}
GList *
meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
{
return update->crtc_gammas;
}
gboolean
meta_kms_update_has_mode_set (MetaKmsUpdate *update)
{
@ -231,6 +284,8 @@ meta_kms_update_free (MetaKmsUpdate *update)
(GDestroyNotify) meta_kms_mode_set_free);
g_list_free_full (update->page_flips, g_free);
g_list_free_full (update->connector_properties, g_free);
g_list_free_full (update->crtc_gammas,
(GDestroyNotify) meta_kms_crtc_gamma_free);
g_free (update);
}

View File

@ -65,6 +65,13 @@ MetaKmsPlaneAssignment * meta_kms_update_assign_plane (MetaKmsUpdate *upd
MetaFixed16Rectangle src_rect,
MetaFixed16Rectangle dst_rect);
void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
gsize size,
unsigned short *red,
unsigned short *green,
unsigned short *blue);
void meta_kms_update_page_flip (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
const MetaKmsPageFlipFeedback *feedback,

View File

@ -367,82 +367,8 @@ meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
unsigned short **green,
unsigned short **blue)
{
MetaGpu *gpu = meta_crtc_get_gpu (crtc);
int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu));
drmModeCrtc *kms_crtc;
kms_crtc = drmModeGetCrtc (kms_fd, crtc->crtc_id);
*size = kms_crtc->gamma_size;
*red = g_new (unsigned short, *size);
*green = g_new (unsigned short, *size);
*blue = g_new (unsigned short, *size);
drmModeCrtcGetGamma (kms_fd, crtc->crtc_id, *size, *red, *green, *blue);
drmModeFreeCrtc (kms_crtc);
}
static char *
generate_gamma_ramp_string (size_t size,
unsigned short *red,
unsigned short *green,
unsigned short *blue)
{
GString *string;
int color;
string = g_string_new ("[");
for (color = 0; color < 3; color++)
{
unsigned short **color_ptr;
char color_char;
size_t i;
switch (color)
{
case 0:
color_ptr = &red;
color_char = 'r';
break;
case 1:
color_ptr = &green;
color_char = 'g';
break;
case 2:
color_ptr = &blue;
color_char = 'b';
break;
}
g_string_append_printf (string, " %c: ", color_char);
for (i = 0; i < MIN (4, size); i++)
{
int j;
if (size > 4)
{
if (i == 2)
g_string_append (string, ",...");
if (i >= 2)
j = i + (size - 4);
else
j = i;
}
else
{
j = i;
}
g_string_append_printf (string, "%s%hu",
j == 0 ? "" : ",",
(*color_ptr)[i]);
}
}
g_string_append (string, " ]");
return g_string_free (string, FALSE);
meta_kms_crtc_get_gamma (meta_crtc_kms_get_kms_crtc (crtc),
size, red, green, blue);
}
static void
@ -453,20 +379,19 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
unsigned short *green,
unsigned short *blue)
{
MetaGpu *gpu = meta_crtc_get_gpu (crtc);
int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu));
g_autofree char *gamma_ramp_string = NULL;
int ret;
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
MetaKmsUpdate *kms_update;
g_autoptr (GError) error = NULL;
gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue);
g_debug ("Setting CRTC (%ld) gamma to %s", crtc->crtc_id, gamma_ramp_string);
kms_update = meta_kms_ensure_pending_update (kms);
meta_kms_update_set_crtc_gamma (kms_update,
meta_crtc_kms_get_kms_crtc (crtc),
size, red, green, blue);
ret = drmModeCrtcSetGamma (kms_fd, crtc->crtc_id, size, red, green, blue);
if (ret != 0)
{
g_warning ("Failed to set CRTC (%ld) Gamma: %s",
crtc->crtc_id, g_strerror (-ret));
}
if (!meta_kms_post_pending_update_sync (kms, &error))
g_warning ("Failed to set CRTC gamma: %s", error->message);
}
static void