libdrm: speed up connector & mode fetching
authorJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 30 Mar 2009 21:35:30 +0000 (14:35 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 30 Mar 2009 21:37:04 +0000 (14:37 -0700)
This patch speeds up drmModeGetConnector by pre-allocating mode &
property info space before calling into the kernel.  In many cases this
pre-allocation will be sufficient to hold the returned values (it's easy
enough to tweak if the common case becomes larger), which means we don't
have to make the second call, which saves a lot of time.

Acked-by: Jakob Bornecrantz <wallbraker@gmail.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
libdrm/xf86drmMode.c

index 872604f..e2aba81 100644 (file)
@@ -357,21 +357,45 @@ drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
 {
        struct drm_mode_get_connector conn;
        drmModeConnectorPtr r = NULL;
+       int pre_props = 8, pre_modes = 16, pre_encoders = 4;
 
        conn.connector_id = connector_id;
        conn.connector_type_id = 0;
        conn.connector_type  = 0;
-       conn.count_modes  = 0;
-       conn.modes_ptr    = 0;
-       conn.count_props  = 0;
-       conn.props_ptr    = 0;
-       conn.prop_values_ptr = 0;
-       conn.count_encoders  = 0;
-       conn.encoders_ptr = 0;
+       conn.count_modes  = pre_modes;
+       conn.count_props  = pre_props;
+       conn.count_encoders  = pre_encoders;
+
+       /*
+        * Pre-allocate space for some modes, properties, and encoders.  If
+        * we're lucky we won't need to call into the kernel twice.
+        */
+       conn.props_ptr = VOID2U64(drmMalloc(pre_props * sizeof(uint32_t)));
+       conn.prop_values_ptr = VOID2U64(drmMalloc(pre_props *
+                                                 sizeof(uint64_t)));
+       conn.modes_ptr = VOID2U64(drmMalloc(pre_modes *
+                                           sizeof(struct drm_mode_modeinfo)));
+       conn.encoders_ptr = VOID2U64(drmMalloc(pre_encoders *
+                                              sizeof(uint32_t)));
 
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
                return 0;
 
+       if (conn.count_props <= pre_props &&
+           conn.count_modes <= pre_modes &&
+           conn.count_encoders <= pre_encoders)
+               goto done;
+
+       /* Oh well, free & reallocate everything and ask again... */
+       drmFree(U642VOID(conn.prop_values_ptr));
+       drmFree(U642VOID(conn.props_ptr));
+       drmFree(U642VOID(conn.modes_ptr));
+       drmFree(U642VOID(conn.encoders_ptr));
+       conn.prop_values_ptr = 0;
+       conn.props_ptr = 0;
+       conn.modes_ptr = 0;
+       conn.encoders_ptr = 0;
+
        if (conn.count_props) {
                conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
                conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
@@ -386,6 +410,7 @@ drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
                goto err_allocs;
 
+done:
        if(!(r = drmMalloc(sizeof(*r)))) {
                goto err_allocs;
        }