xf86-video-intel: configure.ac tools/dri3info.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Apr 1 04:57:06 PDT 2015


 configure.ac     |    2 
 tools/dri3info.c |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 201 insertions(+), 12 deletions(-)

New commits:
commit 2f047c62783a187067921e1aaf5572fb8647bd84
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Apr 1 12:39:48 2015 +0100

    tools/dri3info: Query refresh rate on Primary monitor
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 6d5fe44..f91e6d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -275,7 +275,7 @@ if test "x$shm" = "xyes"; then
 	AC_DEFINE([HAVE_MIT_SHM], 1, [Define to 1 if MIT-SHM is available])
 fi
 
-PKG_CHECK_MODULES(X11_DRI3, [xcb-dri3 xcb-sync xcb-xfixes xcb-present x11-xcb xshmfence x11 xrender xext libdrm], [x11_dri3="yes"], [x11_dri3="no"])
+PKG_CHECK_MODULES(X11_DRI3, [xcb-dri3 xcb-sync xcb-xfixes xcb-present x11-xcb xshmfence x11 xrender xrandr xxf86vm xext libdrm], [x11_dri3="yes"], [x11_dri3="no"])
 AM_CONDITIONAL(X11_DRI3, test "x$x11_dri3" = "xyes" -a "x$shm" = "xyes")
 AM_CONDITIONAL(X11_SHM, test "x$shm" = "xyes")
 
diff --git a/tools/dri3info.c b/tools/dri3info.c
index 6587411..2c2ef95 100644
--- a/tools/dri3info.c
+++ b/tools/dri3info.c
@@ -29,17 +29,63 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <drm.h>
 #include <xf86drm.h>
 
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/xf86vmode.h>
+
+static int dri3_query_version(Display *dpy, int *major, int *minor)
+{
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	xcb_dri3_query_version_reply_t *reply;
+	xcb_generic_error_t *error;
+
+	*major = *minor = -1;
+
+	reply = xcb_dri3_query_version_reply(c,
+					     xcb_dri3_query_version(c,
+								    XCB_DRI3_MAJOR_VERSION,
+								    XCB_DRI3_MINOR_VERSION),
+					     &error);
+	free(error);
+	if (reply == NULL)
+		return -1;
+
+	*major = reply->major_version;
+	*minor = reply->minor_version;
+	free(reply);
+
+	return 0;
+}
+
+static int dri3_exists(Display *dpy)
+{
+	const xcb_query_extension_reply_t *ext;
+	int major, minor;
+
+	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
+	if (ext == NULL || !ext->present)
+		return 0;
+
+	if (dri3_query_version(dpy, &major, &minor) < 0)
+		return 0;
+
+	return major >= 0;
+}
+
 static int dri3_open(Display *dpy)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	xcb_dri3_open_cookie_t cookie;
 	xcb_dri3_open_reply_t *reply;
 
+	if (!dri3_exists(dpy))
+		return -1;
+
 	cookie = xcb_dri3_open(c, RootWindow(dpy, DefaultScreen(dpy)), None);
 	reply = xcb_dri3_open_reply(c, cookie, NULL);
 
@@ -94,12 +140,149 @@ static void get_driver_name(int fd, char *name, int len)
 	(void)drmIoctl(fd, DRM_IOCTL_VERSION, &version);
 }
 
+static int compute_refresh_rate_from_mode(long n, long d, unsigned flags,
+					   int32_t *numerator,
+					   int32_t *denominator)
+{
+	int i;
+
+	/* The mode flags are only defined privately to the Xserver (in xf86str.h)
+	 * but they at least bit compatible between VidMode, RandR and DRM.
+	 */
+# define V_INTERLACE 0x010
+# define V_DBLSCAN   0x020
+
+	if (flags & V_INTERLACE)
+		n *= 2;
+	else if (flags & V_DBLSCAN)
+		d *= 2;
+
+	/* The OML_sync_control spec requires that if the refresh rate is a
+	 * whole number, that the returned numerator be equal to the refresh
+	 * rate and the denominator be 1.
+	 */
+
+	if (n % d == 0) {
+		n /= d;
+		d = 1;
+	}
+	else {
+		static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
+
+		/* This is a poor man's way to reduce a fraction.  It's far from
+		 * perfect, but it will work well enough for this situation.
+		 */
+
+		for (i = 0; f[i] != 0; i++) {
+			while (n % f[i] == 0 && d % f[i] == 0) {
+				d /= f[i];
+				n /= f[i];
+			}
+		}
+	}
+
+	*numerator = n;
+	*denominator = d;
+	return 1;
+}
+
+static int RRGetMscRate(Display *dpy, int32_t *numerator, int32_t *denominator)
+{
+	int ret = 0;
+	Window root = RootWindow(dpy, DefaultScreen(dpy));
+	XRRScreenResources *res;
+	int rr_event, rr_error;
+	RROutput primary;
+	RRMode mode = 0;
+	int n;
+
+	if (!XRRQueryExtension(dpy, &rr_event, &rr_error))
+		return ret;
+
+	res = XRRGetScreenResourcesCurrent(dpy, root);
+	if (res == NULL)
+		return ret;
+
+	/* Use the primary output if specified, otherwise
+	 * use the mode on the first enabled crtc.
+	 */
+	primary = XRRGetOutputPrimary(dpy, root);
+	if (primary) {
+		XRROutputInfo *output;
+
+		output = XRRGetOutputInfo(dpy, res, primary);
+		if (output != NULL) {
+			if (output->crtc) {
+				XRRCrtcInfo *crtc;
+
+				crtc = XRRGetCrtcInfo(dpy, res, output->crtc);
+				if (crtc) {
+					mode = crtc->mode;
+					XRRFreeCrtcInfo(crtc);
+				}
+			}
+			XRRFreeOutputInfo(output);
+		}
+	}
+
+	for (n = 0; mode == 0 && n < res->ncrtc; n++) {
+		XRRCrtcInfo *crtc;
+
+		crtc = XRRGetCrtcInfo(dpy, res, res->crtcs[n]);
+		if (crtc) {
+			mode = crtc->mode;
+			XRRFreeCrtcInfo(crtc);
+		}
+	}
+
+	for (n = 0; n < res->nmode; n++) {
+		if (res->modes[n].id == mode) {
+			ret = compute_refresh_rate_from_mode(res->modes[n].dotClock,
+							     res->modes[n].hTotal*res->modes[n].vTotal,
+							     res->modes[n].modeFlags,
+							     numerator, denominator);
+			break;
+		}
+	}
+
+	XRRFreeScreenResources(res);
+	return ret;
+}
+
+static int VMGetMscRate(Display *dpy, int32_t *numerator, int32_t *denominator)
+{
+	XF86VidModeModeLine mode_line;
+	int dot_clock;
+	int i;
+
+	if (XF86VidModeQueryVersion(dpy, &i, &i) &&
+	    XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &dot_clock, &mode_line))
+		return compute_refresh_rate_from_mode(dot_clock * 1000,
+						      mode_line.vtotal * mode_line.htotal,
+						      mode_line.flags,
+						      numerator, denominator);
+
+	return 0;
+}
+
+static int get_refresh_rate(Display *dpy,
+			     int32_t *numerator,
+			     int32_t *denominator)
+{
+	if (RRGetMscRate(dpy, numerator, denominator))
+		return 1;
+
+	if (VMGetMscRate(dpy, numerator, denominator))
+		return 1;
+
+	return 0;
+}
+
 static void info(const char *dpyname)
 {
 	Display *dpy;
 	int device;
-	char device_path[1024];
-	char driver_name[1024];
+	int32_t numerator, denominator;
 
 	dpy = XOpenDisplay(dpyname);
 	if (dpy == NULL) {
@@ -108,21 +291,27 @@ static void info(const char *dpyname)
 		return;
 	}
 
+	printf("Display '%s'\n", DisplayString(dpy));
 	device = dri3_open(dpy);
 	if (device < 0) {
-		printf("Unable to connect to DRI3 on display '%s'\n",
-		       DisplayString(dpy));
-		return;
-	}
+		printf("\tUnable to connect to DRI3\n");
+	} else {
+		char device_path[1024];
+		char driver_name[1024];
 
-	get_device_path(device, device_path, sizeof(device_path));
-	get_driver_name(device, driver_name, sizeof(driver_name));
+		get_device_path(device, device_path, sizeof(device_path));
+		get_driver_name(device, driver_name, sizeof(driver_name));
+
+		printf("Connected to DRI3, using fd %d which matches %s, driver %s\n",
+		       device, device_path, driver_name);
+		close(device);
+	}
 
-	printf("Connected to DRI3 on display '%s', using fd %d: matches %s, driver %s\n",
-	       DisplayString(dpy), device, device_path, driver_name);
+	if (get_refresh_rate(dpy, &numerator, &denominator))
+		printf("\tPrimary refresh rate: %d/%d (%.1fHz)\n",
+		       numerator, denominator, numerator/(float)denominator);
 
 	XCloseDisplay(dpy);
-	close(device);
 }
 
 int main(int argc, char **argv)


More information about the xorg-commit mailing list