monitor-manager/kms: Use KMS abstraction to get and set CRTC gamma

Still doesn't synchronize with frame drawing, but no point in doing that
until gamma is managed by mutter itself and not gnome-settings-daemon.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/634
This commit is contained in:
Jonas Ådahl 2019-05-03 19:20:21 +02:00 committed by Georges Basile Stavracas Neto
parent c655166398
commit 68f18f1fe9
6 changed files with 191 additions and 21 deletions

View File

@ -40,6 +40,17 @@ struct _MetaKmsCrtc
G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
void
meta_kms_crtc_set_gamma (MetaKmsCrtc *crtc,
MetaKmsUpdate *update,
int size,
const uint16_t *red,
const uint16_t *green,
const uint16_t *blue)
{
meta_kms_update_set_crtc_gamma (update, crtc, size, red, green, blue);
}
MetaKmsDevice * MetaKmsDevice *
meta_kms_crtc_get_device (MetaKmsCrtc *crtc) meta_kms_crtc_get_device (MetaKmsCrtc *crtc)
{ {
@ -64,6 +75,36 @@ meta_kms_crtc_get_idx (MetaKmsCrtc *crtc)
return crtc->idx; return crtc->idx;
} }
static void
read_gamma_state (MetaKmsCrtc *crtc,
MetaKmsImplDevice *impl_device,
drmModeCrtc *drm_crtc)
{
MetaKmsCrtcState *current_state = &crtc->current_state;
if (current_state->gamma.size != drm_crtc->gamma_size)
{
current_state->gamma.size = drm_crtc->gamma_size;
current_state->gamma.red = g_realloc_n (current_state->gamma.red,
drm_crtc->gamma_size,
sizeof (uint16_t));
current_state->gamma.green = g_realloc_n (current_state->gamma.green,
drm_crtc->gamma_size,
sizeof (uint16_t));
current_state->gamma.blue = g_realloc_n (current_state->gamma.blue,
drm_crtc->gamma_size,
sizeof (uint16_t));
}
drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device),
crtc->id,
current_state->gamma.size,
current_state->gamma.red,
current_state->gamma.green,
current_state->gamma.blue);
}
static void static void
meta_kms_crtc_read_state (MetaKmsCrtc *crtc, meta_kms_crtc_read_state (MetaKmsCrtc *crtc,
MetaKmsImplDevice *impl_device, MetaKmsImplDevice *impl_device,
@ -79,6 +120,8 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc,
.is_drm_mode_valid = drm_crtc->mode_valid, .is_drm_mode_valid = drm_crtc->mode_valid,
.drm_mode = drm_crtc->mode, .drm_mode = drm_crtc->mode,
}; };
read_gamma_state (crtc, impl_device, drm_crtc);
} }
void void
@ -109,6 +152,18 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
return crtc; return crtc;
} }
static void
meta_kms_crtc_finalize (GObject *object)
{
MetaKmsCrtc *crtc = META_KMS_CRTC (object);
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);
G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object);
}
static void static void
meta_kms_crtc_init (MetaKmsCrtc *crtc) meta_kms_crtc_init (MetaKmsCrtc *crtc)
{ {
@ -117,4 +172,7 @@ meta_kms_crtc_init (MetaKmsCrtc *crtc)
static void static void
meta_kms_crtc_class_init (MetaKmsCrtcClass *klass) meta_kms_crtc_class_init (MetaKmsCrtcClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_kms_crtc_finalize;
} }

View File

@ -36,6 +36,14 @@ typedef struct _MetaKmsCrtcState
uint32_t common_possible_crtcs; uint32_t common_possible_crtcs;
uint32_t common_possible_clones; uint32_t common_possible_clones;
uint32_t encoder_device_idxs; uint32_t encoder_device_idxs;
struct {
uint16_t *red;
uint16_t *green;
uint16_t *blue;
int size;
} gamma;
} MetaKmsCrtcState; } MetaKmsCrtcState;
#define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ()) #define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ())
@ -43,6 +51,13 @@ G_DECLARE_FINAL_TYPE (MetaKmsCrtc, meta_kms_crtc,
META, KMS_CRTC, META, KMS_CRTC,
GObject) GObject)
void meta_kms_crtc_set_gamma (MetaKmsCrtc *crtc,
MetaKmsUpdate *update,
int size,
const uint16_t *red,
const uint16_t *green,
const uint16_t *blue);
MetaKmsDevice * meta_kms_crtc_get_device (MetaKmsCrtc *crtc); MetaKmsDevice * meta_kms_crtc_get_device (MetaKmsCrtc *crtc);
const MetaKmsCrtcState * meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc); const MetaKmsCrtcState * meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc);

View File

@ -284,6 +284,35 @@ process_mode_set (MetaKmsImpl *impl,
return TRUE; return TRUE;
} }
static gboolean
process_crtc_gamma (MetaKmsImpl *impl,
MetaKmsCrtcGamma *gamma,
GError **error)
{
MetaKmsCrtc *crtc = gamma->crtc;
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc);
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
int fd;
int ret;
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModeCrtcSetGamma (fd, meta_kms_crtc_get_id (crtc),
gamma->size,
gamma->red,
gamma->green,
gamma->blue);
if (ret != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModeCrtcSetGamma on CRTC %u failed: %s",
meta_kms_crtc_get_id (crtc),
g_strerror (-ret));
return FALSE;
}
return TRUE;
}
static gboolean static gboolean
is_timestamp_earlier_than (uint64_t ts1, is_timestamp_earlier_than (uint64_t ts1,
uint64_t ts2) uint64_t ts2)
@ -708,6 +737,14 @@ meta_kms_impl_simple_process_update (MetaKmsImpl *impl,
goto discard_page_flips; goto discard_page_flips;
} }
for (l = meta_kms_update_get_crtc_gammas (update); l; l = l->next)
{
MetaKmsCrtcGamma *gamma = l->data;
if (!process_crtc_gamma (impl, gamma, error))
goto discard_page_flips;
}
for (l = meta_kms_update_get_page_flips (update); l; l = l->next) for (l = meta_kms_update_get_page_flips (update); l; l = l->next)
{ {
MetaKmsPageFlip *page_flip = l->data; MetaKmsPageFlip *page_flip = l->data;

View File

@ -59,6 +59,15 @@ typedef struct _MetaKmsConnectorProperty
uint64_t value; uint64_t value;
} MetaKmsConnectorProperty; } MetaKmsConnectorProperty;
typedef struct _MetaKmsCrtcGamma
{
MetaKmsCrtc *crtc;
int size;
uint16_t *red;
uint16_t *green;
uint16_t *blue;
} MetaKmsCrtcGamma;
typedef struct _MetaKmsPageFlip typedef struct _MetaKmsPageFlip
{ {
MetaKmsCrtc *crtc; MetaKmsCrtc *crtc;
@ -77,6 +86,13 @@ void meta_kms_update_set_connector_property (MetaKmsUpdate *update,
uint32_t prop_id, uint32_t prop_id,
uint64_t value); uint64_t value);
void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
int size,
const uint16_t *red,
const uint16_t *green,
const uint16_t *blue);
void meta_kms_plane_assignment_set_plane_property (MetaKmsPlaneAssignment *plane_assignment, void meta_kms_plane_assignment_set_plane_property (MetaKmsPlaneAssignment *plane_assignment,
uint32_t prop_id, uint32_t prop_id,
uint64_t value); uint64_t value);
@ -89,6 +105,8 @@ GList * meta_kms_update_get_page_flips (MetaKmsUpdate *update);
GList * meta_kms_update_get_connector_properties (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); gboolean meta_kms_update_has_mode_set (MetaKmsUpdate *update);
#endif /* META_KMS_UPDATE_PRIVATE_H */ #endif /* META_KMS_UPDATE_PRIVATE_H */

View File

@ -34,6 +34,7 @@ struct _MetaKmsUpdate
GList *plane_assignments; GList *plane_assignments;
GList *page_flips; GList *page_flips;
GList *connector_properties; GList *connector_properties;
GList *crtc_gammas;
}; };
static MetaKmsProperty * static MetaKmsProperty *
@ -142,6 +143,39 @@ meta_kms_update_set_connector_property (MetaKmsUpdate *update,
prop); prop);
} }
static void
meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma)
{
g_free (gamma->red);
g_free (gamma->green);
g_free (gamma->blue);
g_free (gamma);
}
void
meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
int size,
const uint16_t *red,
const uint16_t *green,
const uint16_t *blue)
{
MetaKmsCrtcGamma *gamma;
g_assert (!meta_kms_update_is_sealed (update));
gamma = g_new0 (MetaKmsCrtcGamma, 1);
*gamma = (MetaKmsCrtcGamma) {
.crtc = crtc,
.size = size,
.red = g_memdup (red, size * sizeof *red),
.green = g_memdup (green, size * sizeof *green),
.blue = g_memdup (blue, size * sizeof *blue),
};
update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma);
}
void void
meta_kms_update_page_flip (MetaKmsUpdate *update, meta_kms_update_page_flip (MetaKmsUpdate *update,
MetaKmsCrtc *crtc, MetaKmsCrtc *crtc,
@ -225,6 +259,12 @@ meta_kms_update_get_connector_properties (MetaKmsUpdate *update)
return update->connector_properties; return update->connector_properties;
} }
GList *
meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
{
return update->crtc_gammas;
}
gboolean gboolean
meta_kms_update_has_mode_set (MetaKmsUpdate *update) meta_kms_update_has_mode_set (MetaKmsUpdate *update)
{ {
@ -258,6 +298,7 @@ meta_kms_update_free (MetaKmsUpdate *update)
(GDestroyNotify) meta_kms_mode_set_free); (GDestroyNotify) meta_kms_mode_set_free);
g_list_free_full (update->page_flips, g_free); g_list_free_full (update->page_flips, g_free);
g_list_free_full (update->connector_properties, 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); g_free (update);
} }

View File

@ -367,20 +367,16 @@ meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
unsigned short **green, unsigned short **green,
unsigned short **blue) unsigned short **blue)
{ {
MetaGpu *gpu = meta_crtc_get_gpu (crtc); MetaKmsCrtc *kms_crtc;
int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu)); const MetaKmsCrtcState *crtc_state;
drmModeCrtc *kms_crtc;
kms_crtc = drmModeGetCrtc (kms_fd, crtc->crtc_id); kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
crtc_state = meta_kms_crtc_get_current_state (kms_crtc);
*size = kms_crtc->gamma_size; *size = crtc_state->gamma.size;
*red = g_new (unsigned short, *size); *red = g_memdup (crtc_state->gamma.red, *size * sizeof **red);
*green = g_new (unsigned short, *size); *green = g_memdup (crtc_state->gamma.green, *size * sizeof **green);
*blue = g_new (unsigned short, *size); *blue = g_memdup (crtc_state->gamma.blue, *size * sizeof **blue);
drmModeCrtcGetGamma (kms_fd, crtc->crtc_id, *size, *red, *green, *blue);
drmModeFreeCrtc (kms_crtc);
} }
static char * static char *
@ -453,20 +449,25 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
unsigned short *green, unsigned short *green,
unsigned short *blue) unsigned short *blue)
{ {
MetaGpu *gpu = meta_crtc_get_gpu (crtc); MetaBackend *backend = meta_monitor_manager_get_backend (manager);
int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu)); MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
MetaKmsCrtc *kms_crtc;
g_autofree char *gamma_ramp_string = NULL; g_autofree char *gamma_ramp_string = NULL;
int ret; MetaKmsUpdate *kms_update;
g_autoptr (GError) error = NULL;
gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue); 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); g_debug ("Setting CRTC (%ld) gamma to %s", crtc->crtc_id, gamma_ramp_string);
ret = drmModeCrtcSetGamma (kms_fd, crtc->crtc_id, size, red, green, blue); kms_update = meta_kms_ensure_pending_update (kms);
if (ret != 0)
{ kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
g_warning ("Failed to set CRTC (%ld) Gamma: %s", meta_kms_crtc_set_gamma (kms_crtc, kms_update,
crtc->crtc_id, g_strerror (-ret)); size, red, green, blue);
}
if (!meta_kms_post_pending_update_sync (kms, &error))
g_warning ("Failed to CRTC gamma: %s", error->message);
} }
static void static void