diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h index 27cb0c08d6ea12b667bad96c1b7d2c6f9164b58b..62c447e96128d6507fe703bcc6d6af665a084b98 100644 --- a/src/backends/native/meta-kms-crtc-private.h +++ b/src/backends/native/meta-kms-crtc-private.h @@ -28,6 +28,7 @@ typedef enum _MetaKmsCrtcProp META_KMS_CRTC_PROP_ACTIVE, META_KMS_CRTC_PROP_GAMMA_LUT, META_KMS_CRTC_PROP_GAMMA_LUT_SIZE, + META_KMS_CRTC_PROP_OUT_FENCE_PTR, META_KMS_CRTC_N_PROPS } MetaKmsCrtcProp; diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index d89b1259895f68a67cfc3aa4f6b62674c36dc8ff..87839e7637f7bec514ab7ff48442b0289ab4246d 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -427,6 +427,11 @@ init_properties (MetaKmsCrtc *crtc, .name = "GAMMA_LUT_SIZE", .type = DRM_MODE_PROP_RANGE, }, + [META_KMS_CRTC_PROP_OUT_FENCE_PTR] = + { + .name = "OUT_FENCE_PTR", + .type = DRM_MODE_PROP_RANGE, + }, } }; } diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c index 2ca70326fa6f9b9a7d8bdb94b32be4d45579609a..4300edd7686816c1a0521426b49353cfbb752411 100644 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ b/src/backends/native/meta-kms-impl-device-atomic.c @@ -19,6 +19,8 @@ #include "backends/native/meta-kms-impl-device-atomic.h" +#include + #include "backends/native/meta-backend-native-private.h" #include "backends/native/meta-kms-connector-private.h" #include "backends/native/meta-kms-crtc-private.h" @@ -415,6 +417,77 @@ process_mode_set (MetaKmsImplDevice *impl_device, return TRUE; } +static gboolean +process_out_fence_ptr (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; + + mode_set->out_fence_fd = -1; + + if ((mode_set->mode || meta_kms_crtc_get_current_state (crtc)->is_active) && + !add_crtc_property (impl_device, + crtc, req, + META_KMS_CRTC_PROP_OUT_FENCE_PTR, + (ptrdiff_t)&mode_set->out_fence_fd, + error)) + return FALSE; + + return TRUE; +} + +static gboolean +process_wait_out_fence (MetaKmsImplDevice *impl_device, + MetaKmsUpdate *update, + drmModeAtomicReq *req, + GArray *blob_ids, + gpointer update_entry, + gpointer user_data, + GError **error) +{ + MetaKmsModeSet *mode_set = update_entry; + GPollFD poll_fd; + int status; + + if (mode_set->out_fence_fd == -1) + return TRUE; + + poll_fd.fd = mode_set->out_fence_fd; + poll_fd.events = G_IO_IN; + poll_fd.revents = 0; + + do + { + status = g_poll (&poll_fd, 1, -1); + + if (status < 0 && errno != EINTR) + { + g_set_error_literal (error, G_IO_ERROR, + g_io_error_from_errno (errno), + strerror (errno)); + return FALSE; + } + } + while (status <= 0); + + if (!g_clear_fd (&mode_set->out_fence_fd, error)) + return FALSE; + + if (poll_fd.revents & G_IO_IN) + return TRUE; + + g_set_error (error, G_FILE_ERROR, + G_FILE_ERROR_FAILED, + "Out fence failed to signal"); + return FALSE; +} + static gboolean add_plane_property (MetaKmsImplDevice *impl_device, MetaKmsPlane *plane, @@ -856,9 +929,9 @@ commit_flags_string (uint32_t commit_flags) } static gboolean -disable_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) +disable_planes_and_connectors (MetaKmsImplDevice *impl_device, + drmModeAtomicReq *req, + GError **error) { GList *l; @@ -874,16 +947,6 @@ disable_connectors (MetaKmsImplDevice *impl_device, 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; @@ -906,48 +969,6 @@ disable_planes (MetaKmsImplDevice *impl_device, 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 MetaKmsFeedback * meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, @@ -958,7 +979,7 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, drmModeAtomicReq *req; g_autoptr (GArray) blob_ids = NULL; int fd; - uint32_t commit_flags = 0; + uint32_t commit_flags = DRM_MODE_ATOMIC_NONBLOCK; int ret; blob_ids = g_array_new (FALSE, TRUE, sizeof (uint32_t)); @@ -1022,11 +1043,23 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, if (meta_kms_update_get_needs_modeset (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_flags |= DRM_MODE_PAGE_FLIP_EVENT; + } + else + { + if (!process_entries (impl_device, + update, + req, + blob_ids, + meta_kms_update_get_mode_sets (update), + NULL, + process_out_fence_ptr, + &error)) + goto err; + } if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY) commit_flags |= DRM_MODE_ATOMIC_TEST_ONLY; @@ -1055,6 +1088,17 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, process_page_flip_listener, NULL); + if (!(commit_flags & DRM_MODE_PAGE_FLIP_EVENT) && + !process_entries (impl_device, + update, + req, + blob_ids, + meta_kms_update_get_mode_sets (update), + NULL, + process_wait_out_fence, + NULL)) + goto err; + release_blob_ids (impl_device, blob_ids); return meta_kms_feedback_new_passed (NULL); @@ -1073,48 +1117,32 @@ err: static void meta_kms_impl_device_atomic_disable (MetaKmsImplDevice *impl_device) { - g_autoptr (GError) error = NULL; - drmModeAtomicReq *req; - int fd; - int ret; + MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); + MetaKmsUpdate *update; + GList *l; meta_topic (META_DEBUG_KMS, "[atomic] Disabling '%s'", meta_kms_impl_device_get_path (impl_device)); - 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; - } + update = meta_kms_update_new (device); - if (!disable_connectors (impl_device, req, &error)) - goto err; - if (!disable_planes (impl_device, req, &error)) - goto err; - if (!disable_crtcs (impl_device, req, &error)) - goto err; + for (l = meta_kms_impl_device_peek_crtcs (impl_device); l; l = l->next) + { + MetaKmsCrtc *crtc = l->data; - meta_topic (META_DEBUG_KMS, "[atomic] Committing disable-device transaction"); + if (!meta_kms_crtc_get_current_state (crtc)->is_active) + continue; - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeAtomicCommit (fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, 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; - } + update = meta_kms_update_new (device); + meta_kms_update_set_flushing (update, crtc); + meta_kms_update_mode_set (update, crtc, NULL, NULL); - return; + meta_topic (META_DEBUG_KMS, "Posting disable update for CRTC %u", + meta_kms_crtc_get_id (crtc)); -err: - g_warning ("[atomic] Failed to disable device '%s': %s", - meta_kms_impl_device_get_path (impl_device), - error->message); + meta_kms_device_post_update (device, update, + META_KMS_UPDATE_FLAG_NONE); + } } static void diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index bce64d309d4ed4e7f272617dc0ba293cdb79afaa..2736167dd01a06529bd33af6a164edf6346052fb 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -1464,8 +1464,7 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, crtc_frame->await_flush = FALSE; - if (crtc_frame->pending_page_flip && - !meta_kms_update_get_mode_sets (update)) + if (crtc_frame->pending_page_flip) { g_assert (latch_crtc); diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index edddd3e4a433748e77f1a0ef832fe49a92d0b6ee..1509fdbeb982121205c2659833903995f880927c 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -77,6 +77,7 @@ typedef struct _MetaKmsModeSet MetaKmsCrtc *crtc; GList *connectors; MetaKmsMode *mode; + int out_fence_fd; } MetaKmsModeSet; typedef struct _MetaKmsConnectorUpdate