chiark / gitweb /
terminal: allow user-context to be retrieved/stored
[elogind.git] / src / libsystemd-terminal / grdev-drm.c
index 3936a029fa683cec2a9d66db4282eb2dfe949e1e..2e55ad326b15ff3484b52179949673a2497267e0 100644 (file)
@@ -264,6 +264,7 @@ struct grdrm_card {
         Hashmap *object_map;
 
         bool async_hotplug : 1;
+        bool hotplug : 1;
         bool running : 1;
         bool ready : 1;
         bool cap_dumb : 1;
@@ -603,12 +604,19 @@ static int grdrm_connector_resync(grdrm_connector *connector) {
                 res.count_encoders = connector->kern.max_encoders;
                 res.count_props = connector->kern.max_props;
 
-                /* Retrieve modes only if we have none. This avoids expensive
-                 * EDID reads in the kernel, that can slow down resyncs
-                 * considerably! */
-                if (connector->kern.n_modes == 0) {
-                        res.modes_ptr = PTR_TO_UINT64(connector->kern.modes);
-                        res.count_modes = connector->kern.max_modes;
+                /* The kernel reads modes from the EDID information only if we
+                 * pass count_modes==0. This is a legacy hack for libdrm (which
+                 * called every ioctl twice). Now we have to adopt.. *sigh*.
+                 * If we never received an hotplug event, there's no reason to
+                 * sync modes. EDID reads are heavy, so skip that if not
+                 * required. */
+                if (card->hotplug) {
+                        if (tries > 0) {
+                                res.modes_ptr = PTR_TO_UINT64(connector->kern.modes);
+                                res.count_modes = connector->kern.max_modes;
+                        } else {
+                                resized = true;
+                        }
                 }
 
                 r = ioctl(card->fd, DRM_IOCTL_MODE_GETCONNECTOR, &res);
@@ -689,7 +697,6 @@ static int grdrm_connector_resync(grdrm_connector *connector) {
                         continue;
 
                 connector->kern.n_encoders = res.count_encoders;
-                connector->kern.n_modes = res.count_modes;
                 connector->kern.n_props = res.count_props;
                 connector->kern.type = res.connector_type;
                 connector->kern.type_id = res.connector_type_id;
@@ -698,6 +705,8 @@ static int grdrm_connector_resync(grdrm_connector *connector) {
                 connector->kern.mm_width = res.mm_width;
                 connector->kern.mm_height = res.mm_height;
                 connector->kern.subpixel = res.subpixel;
+                if (res.modes_ptr == PTR_TO_UINT64(connector->kern.modes))
+                        connector->kern.n_modes = res.count_modes;
 
                 break;
         }
@@ -1177,8 +1186,12 @@ static int grdrm_crtc_commit_flip(grdrm_crtc *crtc, grdev_fb **slot) {
         r = ioctl(card->fd, DRM_IOCTL_MODE_PAGE_FLIP, &page_flip);
         if (r < 0) {
                 r = -errno;
-                log_debug("grdrm: %s: cannot schedule page-flip on crtc %" PRIu32 ": %m",
-                          card->base.name, crtc->object.id);
+                /* Avoid excessive logging on EINVAL; it is currently not
+                 * possible to see whether cards support page-flipping, so
+                 * avoid logging on each frame. */
+                if (r != -EINVAL)
+                        log_debug("grdrm: %s: cannot schedule page-flip on crtc %" PRIu32 ": %m",
+                                  card->base.name, crtc->object.id);
 
                 if (grdrm_card_async(card, r))
                         return r;
@@ -2145,6 +2158,8 @@ static void grdrm_card_hotplug(grdrm_card *card) {
         if (!card->running)
                 return;
 
+        log_debug("grdrm: %s/%s: reconfigure card", card->base.session->name, card->base.name);
+
         card->ready = false;
         r = grdrm_card_resync(card);
         if (r < 0) {
@@ -2155,9 +2170,13 @@ static void grdrm_card_hotplug(grdrm_card *card) {
 
         grdev_session_pin(card->base.session);
 
-        grdrm_card_print(card);
+        /* debug statement to print card information */
+        if (0)
+                grdrm_card_print(card);
+
         grdrm_card_configure(card);
         card->ready = true;
+        card->hotplug = false;
 
         grdev_session_unpin(card->base.session);
 }
@@ -2365,6 +2384,7 @@ static int grdrm_card_open(grdrm_card *card, int dev_fd) {
 
         sd_event_source_set_enabled(card->fd_src, SD_EVENT_OFF);
 
+        card->hotplug = true;
         card->fd = fd;
         fd = -1;
 
@@ -3020,13 +3040,17 @@ void grdev_drm_card_hotplug(grdev_card *basecard, struct udev_device *ud) {
                 /* If we get add/remove events on DRM nodes without devnum, we
                  * got hotplugged DRM objects so refresh the device. */
                 devnum = udev_device_get_devnum(ud);
-                if (devnum == 0)
+                if (devnum == 0) {
+                        card->hotplug = true;
                         grdrm_card_hotplug(card);
+                }
         } else if (streq_ptr(action, "change")) {
                 /* A change event with HOTPLUG=1 is sent whenever a connector
                  * changed state. Refresh the device to update our state. */
                 p = udev_device_get_property_value(ud, "HOTPLUG");
-                if (streq_ptr(p, "1"))
+                if (streq_ptr(p, "1")) {
+                        card->hotplug = true;
                         grdrm_card_hotplug(card);
+                }
         }
 }