diff options
Diffstat (limited to 'src/backends/native/meta-kms-impl-device-atomic.c')
-rw-r--r-- | src/backends/native/meta-kms-impl-device-atomic.c | 1202 |
1 files changed, 0 insertions, 1202 deletions
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c deleted file mode 100644 index 8e41207ee..000000000 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (C) 2019-2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-atomic.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" - -typedef gboolean (* MetaKmsAtomicProcessFunc) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer entry_data, - gpointer user_data, - GError **error); - -struct _MetaKmsImplDeviceAtomic -{ - MetaKmsImplDevice parent; - - GHashTable *page_flip_datas; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceAtomic, meta_kms_impl_device_atomic, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static uint32_t -store_new_blob (MetaKmsImplDevice *impl_device, - GArray *blob_ids, - const void *data, - size_t size, - GError **error) -{ - int fd = meta_kms_impl_device_get_fd (impl_device); - uint32_t blob_id; - int ret; - - ret = drmModeCreatePropertyBlob (fd, data, size, &blob_id); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCreatePropertyBlob: %s", g_strerror (-ret)); - return 0; - } - - g_array_append_val (blob_ids, blob_id); - - return blob_id; -} - -static void -release_blob_ids (MetaKmsImplDevice *impl_device, - GArray *blob_ids) -{ - int fd = meta_kms_impl_device_get_fd (impl_device); - unsigned int i; - - for (i = 0; i < blob_ids->len; i++) - { - uint32_t blob_id = g_array_index (blob_ids, uint32_t, i); - - drmModeDestroyPropertyBlob (fd, blob_id); - } -} - -static gboolean -add_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - drmModeAtomicReq *req, - MetaKmsConnectorProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Connector property '%s' not found", - meta_kms_connector_get_prop_name (connector, prop)); - return FALSE; - } - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting connector %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_prop_id (connector, prop), - value); - ret = drmModeAtomicAddProperty (req, - meta_kms_connector_get_id (connector), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, connector: %u, prop id: %u: %s", - meta_kms_connector_get_id (connector), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_connector_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsConnectorUpdate *connector_update = update_entry; - MetaKmsConnector *connector = connector_update->connector; - - if (connector_update->underscanning.has_update && - connector_update->underscanning.is_active) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Setting underscanning on connector %u (%s) to " - "%" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - connector_update->underscanning.hborder, - connector_update->underscanning.vborder); - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 1, - error)) - return FALSE; - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - connector_update->underscanning.hborder, - error)) - return FALSE; - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - connector_update->underscanning.vborder, - error)) - return FALSE; - } - else if (connector_update->underscanning.has_update) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Unsetting underscanning on connector %u (%s)", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -add_crtc_property (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc, - drmModeAtomicReq *req, - MetaKmsCrtcProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_crtc_get_prop_id (crtc, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "CRTC property (%s) not found", - meta_kms_crtc_get_prop_name (crtc, prop)); - return FALSE; - } - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting CRTC %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - meta_kms_crtc_get_prop_name (crtc, prop), - meta_kms_crtc_get_prop_id (crtc, prop), - value); - ret = drmModeAtomicAddProperty (req, - meta_kms_crtc_get_id (crtc), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, crtc: %u, prop: %s (%u): %s", - meta_kms_crtc_get_id (crtc), - meta_kms_crtc_get_prop_name (crtc, prop), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_mode_set (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsModeSet *mode_set = update_entry; - MetaKmsCrtc *crtc = mode_set->crtc; - MetaKmsMode *mode; - - mode = (MetaKmsMode *) mode_set->mode; - if (mode) - { - uint32_t mode_id; - GList *l; - - mode_id = meta_kms_mode_create_blob_id (mode, error); - if (mode_id == 0) - return FALSE; - - g_array_append_val (blob_ids, mode_id); - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting mode of CRTC %u (%s) to %s", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - meta_kms_mode_get_name (mode)); - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - mode_id, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 1, - error)) - return FALSE; - - for (l = mode_set->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_CRTC_ID, - meta_kms_crtc_get_id (crtc), - error)) - return FALSE; - } - } - else - { - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - 0, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 0, - error)) - return FALSE; - - meta_topic (META_DEBUG_KMS, - "[atomic] Unsetting mode of (%u, %s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - } - - return TRUE; -} - -static gboolean -add_plane_property (MetaKmsImplDevice *impl_device, - MetaKmsPlane *plane, - drmModeAtomicReq *req, - MetaKmsCrtcProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_plane_get_prop_id (plane, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Plane property (%s) not found on %u", - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_id (plane)); - return FALSE; - } - - switch (meta_kms_plane_get_prop_internal_type (plane, prop)) - { - case META_KMS_PROP_TYPE_RAW: - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_prop_id (plane, prop), - value); - break; - case META_KMS_PROP_TYPE_FIXED_16: - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane %u (%s) property '%s' (%u) to %.2f", - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_prop_id (plane, prop), - meta_fixed_16_to_double (value)); - break; - } - ret = drmModeAtomicAddProperty (req, - meta_kms_plane_get_id (plane), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, plane: %u, prop: %s (%u): %s", - meta_kms_plane_get_id (plane), - meta_kms_plane_get_prop_name (plane, prop), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static const char * -get_plane_type_string (MetaKmsPlane *plane) -{ - switch (meta_kms_plane_get_plane_type (plane)) - { - case META_KMS_PLANE_TYPE_PRIMARY: - return "primary"; - case META_KMS_PLANE_TYPE_CURSOR: - return "cursor"; - case META_KMS_PLANE_TYPE_OVERLAY: - return "overlay"; - } - - g_assert_not_reached (); -} - -static gboolean -process_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPlaneAssignment *plane_assignment = update_entry; - MetaKmsPlane *plane = plane_assignment->plane; - MetaDrmBuffer *buffer; - - buffer = plane_assignment->buffer; - - meta_topic (META_DEBUG_KMS, - "[atomic] Assigning %s plane (%u, %s) to %u, " - "%hdx%hd+%hd+%hd -> %dx%d+%d+%d", - get_plane_type_string (plane), - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - buffer ? meta_drm_buffer_get_fb_id (buffer) : 0, - meta_fixed_16_to_int (plane_assignment->src_rect.width), - meta_fixed_16_to_int (plane_assignment->src_rect.height), - meta_fixed_16_to_int (plane_assignment->src_rect.x), - meta_fixed_16_to_int (plane_assignment->src_rect.y), - plane_assignment->dst_rect.width, - plane_assignment->dst_rect.height, - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - if (buffer) - { - int i; - struct { - MetaKmsPlaneProp prop; - uint64_t value; - } props[] = { - { - .prop = META_KMS_PLANE_PROP_FB_ID, - .value = meta_drm_buffer_get_fb_id (buffer), - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_ID, - .value = meta_kms_crtc_get_id (plane_assignment->crtc), - }, - { - .prop = META_KMS_PLANE_PROP_SRC_X, - .value = plane_assignment->src_rect.x, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_Y, - .value = plane_assignment->src_rect.y, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_W, - .value = plane_assignment->src_rect.width, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_H, - .value = plane_assignment->src_rect.height, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_X, - .value = plane_assignment->dst_rect.x, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_Y, - .value = plane_assignment->dst_rect.y, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_W, - .value = plane_assignment->dst_rect.width, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_H, - .value = plane_assignment->dst_rect.height, - }, - }; - - for (i = 0; i < G_N_ELEMENTS (props); i++) - { - if (!add_plane_property (impl_device, - plane, req, - props[i].prop, - props[i].value, - error)) - return FALSE; - } - } - else - { - int i; - struct { - MetaKmsPlaneProp prop; - uint64_t value; - } props[] = { - { - .prop = META_KMS_PLANE_PROP_FB_ID, - .value = 0, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_ID, - .value = 0, - }, - }; - - for (i = 0; i < G_N_ELEMENTS (props); i++) - { - if (!add_plane_property (impl_device, - plane, req, - props[i].prop, - props[i].value, - error)) - return FALSE; - } - } - - if (plane_assignment->rotation) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane (%u, %s) rotation to %" - G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - plane_assignment->rotation); - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_ROTATION, - plane_assignment->rotation, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_crtc_gamma (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsCrtcGamma *gamma = update_entry; - MetaKmsCrtc *crtc = gamma->crtc; - struct drm_color_lut drm_color_lut[gamma->size]; - int i; - uint32_t color_lut_blob_id; - - for (i = 0; i < gamma->size; i++) - { - drm_color_lut[i].red = gamma->red[i]; - drm_color_lut[i].green = gamma->green[i]; - drm_color_lut[i].blue = gamma->blue[i]; - } - - color_lut_blob_id = store_new_blob (impl_device, - blob_ids, - drm_color_lut, - sizeof drm_color_lut, - error); - if (!color_lut_blob_id) - return FALSE; - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting CRTC (%u, %s) gamma, size: %d", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - gamma->size); - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_GAMMA_LUT, - color_lut_blob_id, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -process_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (impl_device); - MetaKmsPageFlipListener *listener = update_entry; - MetaKmsPageFlipData *page_flip_data; - uint32_t crtc_id; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - crtc_id = meta_kms_crtc_get_id (listener->crtc); - page_flip_data = g_hash_table_lookup (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id)); - if (!page_flip_data) - { - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - g_hash_table_insert (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id), - page_flip_data); - - meta_kms_impl_device_hold_fd (impl_device); - - meta_topic (META_DEBUG_KMS, - "[atomic] Adding page flip data for (%u, %s): %p", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - } - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - return TRUE; -} - -static gboolean -discard_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPageFlipListener *listener = update_entry; - GError *commit_error = user_data; - MetaKmsPageFlipData *page_flip_data; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - - meta_topic (META_DEBUG_KMS, - "[atomic] Creating transient page flip data for (%u, %s): %p", - meta_kms_crtc_get_id (listener->crtc), - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, commit_error); - - return TRUE; -} - -static gboolean -process_entries (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - GList *entries, - gpointer user_data, - MetaKmsAtomicProcessFunc func, - GError **error) -{ - GList *l; - - for (l = entries; l; l = l->next) - { - if (!func (impl_device, - update, - req, - blob_ids, - l->data, - user_data, - error)) - return FALSE; - } - - return TRUE; -} - -static void -atomic_page_flip_handler (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - unsigned int crtc_id, - void *user_data) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = user_data; - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_atomic); - MetaKmsPageFlipData *page_flip_data = NULL; - - g_hash_table_steal_extended (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id), - NULL, - (gpointer *) &page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[atomic] Page flip callback for CRTC (%u, %s), data: %p", - crtc_id, meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - if (!page_flip_data) - return; - - meta_kms_impl_device_unhold_fd (impl_device); - - meta_kms_page_flip_data_set_timings_in_impl (page_flip_data, - sequence, tv_sec, tv_usec); - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); -} - -static void -meta_kms_impl_device_atomic_setup_drm_event_context (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context) -{ - drm_event_context->version = 3; - drm_event_context->page_flip_handler2 = atomic_page_flip_handler; -} - -static const char * -commit_flags_string (uint32_t commit_flags) -{ - static char static_commit_flags_string[255]; - const char *commit_flag_strings[4] = { NULL }; - int i = 0; - g_autofree char *commit_flags_string = NULL; - - if (commit_flags & DRM_MODE_ATOMIC_NONBLOCK) - commit_flag_strings[i++] = "ATOMIC_NONBLOCK"; - if (commit_flags & DRM_MODE_ATOMIC_ALLOW_MODESET) - commit_flag_strings[i++] = "ATOMIC_ALLOW_MODESET"; - if (commit_flags & DRM_MODE_PAGE_FLIP_EVENT) - commit_flag_strings[i++] = "PAGE_FLIP_EVENT"; - - commit_flags_string = g_strjoinv ("|", (char **) commit_flag_strings); - strncpy (static_commit_flags_string, commit_flags_string, - (sizeof static_commit_flags_string) - 1); - - return static_commit_flags_string; -} - -static gboolean -disable_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_CRTC_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_planes (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_planes (impl_device); l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_CRTC_ID, - 0, - error)) - return FALSE; - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_FB_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_crtcs (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_crtcs (impl_device); l; l = l->next) - { - MetaKmsCrtc *crtc = l->data; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 0, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_planes_and_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - if (!disable_connectors (impl_device, req, error)) - return FALSE; - if (!disable_planes (impl_device, req, error)) - return FALSE; - - return TRUE; -} - -static gboolean -process_power_save (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - if (!disable_connectors (impl_device, req, error)) - return FALSE; - if (!disable_planes (impl_device, req, error)) - return FALSE; - if (!disable_crtcs (impl_device, req, error)) - return FALSE; - - return TRUE; -} - -static MetaKmsFeedback * -meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - GError *error = NULL; - GList *failed_planes = NULL; - drmModeAtomicReq *req; - g_autoptr (GArray) blob_ids = NULL; - int fd; - uint32_t commit_flags = 0; - int ret; - - blob_ids = g_array_new (FALSE, TRUE, sizeof (uint32_t)); - - meta_topic (META_DEBUG_KMS, - "[atomic] Processing update %" G_GUINT64_FORMAT, - meta_kms_update_get_sequence_number (update)); - - req = drmModeAtomicAlloc (); - if (!req) - { - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create atomic transaction request: %s", - g_strerror (errno)); - goto err; - } - - if (meta_kms_update_get_mode_sets (update)) - { - if (!disable_planes_and_connectors (impl_device, req, &error)) - goto err; - } - - if (meta_kms_update_is_power_save (update)) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Entering power save mode for %s", - meta_kms_impl_device_get_path (impl_device)); - - if (!process_power_save (impl_device, req, &error)) - goto err; - - commit_flags = DRM_MODE_ATOMIC_ALLOW_MODESET; - goto commit; - } - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_connector_updates (update), - NULL, - process_connector_update, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_mode_sets (update), - NULL, - process_mode_set, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_plane_assignments (update), - NULL, - process_plane_assignment, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_crtc_gammas (update), - NULL, - process_crtc_gamma, - &error)) - goto err; - - if (meta_kms_update_get_mode_sets (update)) - commit_flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - else - commit_flags |= DRM_MODE_ATOMIC_NONBLOCK; - - if (meta_kms_update_get_page_flip_listeners (update)) - commit_flags |= DRM_MODE_PAGE_FLIP_EVENT; - -commit: - meta_topic (META_DEBUG_KMS, - "[atomic] Committing update %" G_GUINT64_FORMAT ", flags: %s", - meta_kms_update_get_sequence_number (update), - commit_flags_string (commit_flags)); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeAtomicCommit (fd, req, commit_flags, impl_device); - drmModeAtomicFree (req); - if (ret < 0) - { - g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicCommit: %s", g_strerror (-ret)); - goto err; - } - - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - NULL, - process_page_flip_listener, - NULL); - - release_blob_ids (impl_device, blob_ids); - - return meta_kms_feedback_new_passed (NULL); - -err: - meta_topic (META_DEBUG_KMS, "[atomic] KMS update failed: %s", error->message); - - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - { - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - error, - discard_page_flip_listener, - NULL); - } - - release_blob_ids (impl_device, blob_ids); - - return meta_kms_feedback_new_failed (failed_planes, error); -} - -static void -meta_kms_impl_device_atomic_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - meta_kms_page_flip_data_flipped_in_impl (page_flip_data); -} - -static void -meta_kms_impl_device_atomic_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ -} - -static gboolean -dispose_page_flip_data (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = value; - MetaKmsImplDevice *impl_device = user_data; - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL); - meta_kms_impl_device_unhold_fd (impl_device); - - return TRUE; -} - -static void -meta_kms_impl_device_atomic_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (impl_device); - - g_hash_table_foreach_remove (impl_device_atomic->page_flip_datas, - dispose_page_flip_data, - impl_device); -} - -static void -meta_kms_impl_device_atomic_finalize (GObject *object) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (object); - - g_assert (g_hash_table_size (impl_device_atomic->page_flip_datas) == 0); - - g_hash_table_unref (impl_device_atomic->page_flip_datas); - - G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object); -} - -static MetaDeviceFile * -meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - error); - if (!device_file) - return NULL; - - if (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC)) - { - int fd = meta_device_file_get_fd (device_file); - - g_warn_if_fail (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE)); - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported"); - return NULL; - } - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_ATOMIC not supported"); - return NULL; - } - - meta_device_file_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC); - } - - return g_steal_pointer (&device_file); -} - -static gboolean -is_atomic_allowed (const char *driver_name) -{ - const char *atomic_driver_deny_list[] = { - "qxl", - "vmwgfx", - "vboxvideo", - "nvidia-drm", - NULL, - }; - - return !g_strv_contains (atomic_driver_deny_list, driver_name); -} - -static gboolean -meta_kms_impl_device_atomic_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - const char *atomic_kms_enable_env; - - atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS"); - if (atomic_kms_enable_env && g_strcmp0 (atomic_kms_enable_env, "1") != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_USER_INHIBITED, - "Atomic mode setting disable via env var"); - return FALSE; - } - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - if (!is_atomic_allowed (meta_kms_impl_device_get_driver_name (impl_device))) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_DENY_LISTED, - "Atomic mode setting disable via driver deny list"); - return FALSE; - } - - if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) - return FALSE; - - g_message ("Added device '%s' (%s) using atomic mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -meta_kms_impl_device_atomic_init (MetaKmsImplDeviceAtomic *impl_device_atomic) -{ - impl_device_atomic->page_flip_datas = g_hash_table_new (NULL, NULL); -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_atomic_initable_init; -} - -static void -meta_kms_impl_device_atomic_class_init (MetaKmsImplDeviceAtomicClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - object_class->finalize = meta_kms_impl_device_atomic_finalize; - - impl_device_class->open_device_file = - meta_kms_impl_device_atomic_open_device_file; - impl_device_class->setup_drm_event_context = - meta_kms_impl_device_atomic_setup_drm_event_context; - impl_device_class->process_update = - meta_kms_impl_device_atomic_process_update; - impl_device_class->handle_page_flip_callback = - meta_kms_impl_device_atomic_handle_page_flip_callback; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_atomic_discard_pending_page_flips; - impl_device_class->prepare_shutdown = - meta_kms_impl_device_atomic_prepare_shutdown; -} |