summaryrefslogtreecommitdiff
path: root/src/backends/native/meta-kms-impl-device-atomic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/native/meta-kms-impl-device-atomic.c')
-rw-r--r--src/backends/native/meta-kms-impl-device-atomic.c1202
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;
-}