Add a new API that allows the caller to skip any forced probing, which
may require slow i2c to a remote display, and only report the currently
active mode and encoder for a Connector. This is often the information
of interest and is much, much faster than re-retrieving the link status
and EDIDs, e.g. if the caller only wishes to count the number of active
outputs.

v2: Fix error path to avoid double free after a failed GETCONNECTOR
ioctl.

v3: Daniel strongly disapproved of my disjoint in behaviour between
GetConnector and GetConnectorCurrent, and considering how best to make a
drop in replacement for drmmode_output_init() convinced me keeping the
API as consistent as possible was the right approach.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter at ffwll.com>
Cc: Damien Lespiau <damien.lespiau at intel.com>
Cc: David Herrmann <dh.herrmann at googlemail.com>
---
 tests/modeprint/modeprint.c | 18 ++++++++++++++++--
 xf86drmMode.c               | 20 +++++++++++++++++---
 xf86drmMode.h               | 17 +++++++++++++++--
 3 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c
index 6f0d039..514d3ba 100644
--- a/tests/modeprint/modeprint.c
+++ b/tests/modeprint/modeprint.c
@@ -43,6 +43,7 @@

 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

+int current;
 int connectors;
 int full_props;
 int edid;
@@ -272,7 +273,7 @@ int printRes(int fd, drmModeResPtr res)

        if (connectors) {
                for (i = 0; i < res->count_connectors; i++) {
-                       connector = drmModeGetConnector(fd, res->connectors[i]);
+                       connector = (current ? drmModeGetConnectorCurrent : 
drmModeGetConnector) (fd, res->connectors[i]);

                        if (!connector)
                                printf("Could not get connector %i\n", 
res->connectors[i]);
@@ -331,6 +332,7 @@ int printRes(int fd, drmModeResPtr res)

 void args(int argc, char **argv)
 {
+       int defaults = 1;
        int i;

        fbs = 0;
@@ -341,32 +343,41 @@ void args(int argc, char **argv)
        full_modes = 0;
        full_props = 0;
        connectors = 0;
+       current = 0;

        module_name = argv[1];

        for (i = 2; i < argc; i++) {
                if (strcmp(argv[i], "-fb") == 0) {
                        fbs = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-crtcs") == 0) {
                        crtcs = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-cons") == 0) {
                        connectors = 1;
                        modes = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-modes") == 0) {
                        connectors = 1;
                        modes = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-full") == 0) {
                        connectors = 1;
                        modes = 1;
                        full_modes = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-props") == 0) {
                        connectors = 1;
                        full_props = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-edids") == 0) {
                        connectors = 1;
                        edid = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-encoders") == 0) {
                        encoders = 1;
+                       defaults = 0;
                } else if (strcmp(argv[i], "-v") == 0) {
                        fbs = 1;
                        edid = 1;
@@ -376,10 +387,13 @@ void args(int argc, char **argv)
                        full_modes = 1;
                        full_props = 1;
                        connectors = 1;
+                       defaults = 0;
+               } else if (strcmp(argv[i], "-current") == 0) {
+                       current = 1;
                }
        }

-       if (argc == 2) {
+       if (defaults) {
                fbs = 1;
                edid = 1;
                crtcs = 1;
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 9ea8fe7..138f1bf 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -476,19 +476,23 @@ drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t 
encoder_id)
 /*
  * Connector manipulation
  */
-
-drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
+static drmModeConnectorPtr
+_drmModeGetConnector(int fd, uint32_t connector_id, int probe)
 {
        struct drm_mode_get_connector conn, counts;
        drmModeConnectorPtr r = NULL;

-retry:
        memclear(conn);
        conn.connector_id = connector_id;
+       if (!probe) {
+               conn.count_modes = 1;
+               conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct 
drm_mode_modeinfo)));
+       }

        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
                return 0;

+retry:
        counts = conn;

        if (conn.count_props) {
@@ -572,6 +576,16 @@ err_allocs:
        return r;
 }

+drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
+{
+       return _drmModeGetConnector(fd, connector_id, 1);
+}
+
+drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id)
+{
+       return _drmModeGetConnector(fd, connector_id, 0);
+}
+
 int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr 
mode_info)
 {
        struct drm_mode_mode_cmd res;
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 856a6bb..278da48 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -422,10 +422,23 @@ drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t 
encoder_id);
  */

 /**
- * Retrive information about the connector connectorId.
+ * Retrieve all information about the connector connectorId. This will do a
+ * forced probe on the connector to retrieve remote information such as EDIDs
+ * from the display device.
  */
 extern drmModeConnectorPtr drmModeGetConnector(int fd,
-               uint32_t connectorId);
+                                              uint32_t connectorId);
+
+/**
+ * Retrieve current information, i.e the currently active mode and encoder,
+ * about the connector connectorId. This will not do any probing on the
+ * connector or remote device, and only reports what is currently known.
+ * For the complete set of modes and encoders associated with the connector
+ * use drmModeGetConnector() which will do a probe to determine any display
+ * link changes first.
+ */
+extern drmModeConnectorPtr drmModeGetConnectorCurrent(int fd,
+                                                     uint32_t connector_id);

 /**
  * Attaches the given mode to an connector.
-- 
2.1.4

Reply via email to