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:
parent
6f436023ed
commit
cf9136ecd6
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user