[Mesa-dev] [PATCH] glx: Report the current refresh rate for GetMscRateOML
Chris Wilson
chris at chris-wilson.co.uk
Fri May 16 06:06:15 PDT 2014
OML_sync_control:
The graphics MSC value is incremented once for each screen refresh.
For a non-interlaced display, this means that the graphics MSC value
is incremented for each frame. For an interlaced display, it means
that it will be incremented for each field. For a multi-monitor
system, the monitor used to determine MSC is screen 0 of <display>.
glXGetMscRateOML returns the rate at which the MSC will be incremented
for the display associated with <hdc>. The rate is expressed in Hertz
as <numerator> / <denominator>. If the MSC rate in Hertz is an
integer, then <denominator> will be 1 and <numerator> will be
the MSC rate.
The current implementation using the XVidMode extension returns the
refresh rate of the initial mode X was started at. As an improvement,
use RandR to query the current mode of the primary output (or first
enabled CRTC) and use that as the basis for the refresh rate calculation.
We fallback to the current XVidMode method if XRandR is not available.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: TheoH <Theo0x48 at gmail.com>
Cc: Jamey Sharp <jamey at minilop.net>
---
configure.ac | 7 +++
src/glx/Makefile.am | 8 ++-
src/glx/glxcmds.c | 160 ++++++++++++++++++++++++++++++++++++++++------------
3 files changed, 136 insertions(+), 39 deletions(-)
diff --git a/configure.ac b/configure.ac
index bf543c2..39e9909 100644
--- a/configure.ac
+++ b/configure.ac
@@ -880,6 +880,12 @@ xyesno)
dri_modules="$dri_modules xcb-dri3 xcb-present xcb-sync xshmfence >= $XSHMFENCE_REQUIRED"
fi
+ # add Xrandr if available
+ PKG_CHECK_MODULES([XRANDR], [xrandr], HAVE_XRANDR=yes, HAVEXRANDR=no)
+ if test "$HAVE_XRANDR" = yes ; then
+ dri_modules="$dri_modules xrandr"
+ fi
+
# add xf86vidmode if available
PKG_CHECK_MODULES([XF86VIDMODE], [xxf86vm], HAVE_XF86VIDMODE=yes, HAVE_XF86VIDMODE=no)
if test "$HAVE_XF86VIDMODE" = yes ; then
@@ -903,6 +909,7 @@ fi
# This is outside the case (above) so that it is invoked even for non-GLX
# builds.
+AM_CONDITIONAL(HAVE_XRANDR, test "x$HAVE_XRANDR" = xyes)
AM_CONDITIONAL(HAVE_XF86VIDMODE, test "x$HAVE_XF86VIDMODE" = xyes)
GLESv1_CM_LIB_DEPS="$LIBDRM_LIBS -lm $PTHREAD_LIBS $DLOPEN_LIBS"
diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am
index 482d952..41b008c 100644
--- a/src/glx/Makefile.am
+++ b/src/glx/Makefile.am
@@ -26,8 +26,12 @@ endif
SUBDIRS=. tests
+EXTRA_DEFINES =
if HAVE_XF86VIDMODE
-EXTRA_DEFINES_XF86VIDMODE = -DXF86VIDMODE
+EXTRA_DEFINES += -DXF86VIDMODE
+endif
+if HAVE_XRANDR
+EXTRA_DEFINES += -DXRANDR
endif
AM_CFLAGS = \
@@ -40,7 +44,7 @@ AM_CFLAGS = \
-I$(top_builddir)/src/mapi/glapi \
$(VISIBILITY_CFLAGS) \
$(SHARED_GLAPI_CFLAGS) \
- $(EXTRA_DEFINES_XF86VIDMODE) \
+ $(EXTRA_DEFINES) \
-D_REENTRANT \
-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \
$(DEFINES) \
diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
index 7984715..7fd7648 100644
--- a/src/glx/glxcmds.c
+++ b/src/glx/glxcmds.c
@@ -45,6 +45,9 @@
#include "apple_glx.h"
#else
#include <sys/time.h>
+#ifdef XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
#ifdef XF86VIDMODE
#include <X11/extensions/xf86vmode.h>
#endif
@@ -2082,63 +2085,146 @@ __glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
return False;
}
-#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
-_X_HIDDEN GLboolean
-__glxGetMscRate(struct glx_screen *psc,
- int32_t * numerator, int32_t * denominator)
+static GLboolean compute_refresh_rate_from_mode(long n, long d, unsigned flags,
+ int32_t *numerator,
+ int32_t *denominator)
{
-#ifdef XF86VIDMODE
- XF86VidModeModeLine mode_line;
- int dot_clock;
int i;
- if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
- XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
- unsigned n = dot_clock * 1000;
- unsigned d = mode_line.vtotal * mode_line.htotal;
-
# define V_INTERLACE 0x010
# define V_DBLSCAN 0x020
- if (mode_line.flags & V_INTERLACE)
- n *= 2;
- else if (mode_line.flags & V_DBLSCAN)
- d *= 2;
+ 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 };
- /* 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.
+ /* 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.
*/
- if (n % d == 0) {
- n /= d;
- d = 1;
+ for (i = 0; f[i] != 0; i++) {
+ while (n % f[i] == 0 && d % f[i] == 0) {
+ d /= f[i];
+ n /= f[i];
+ }
}
- 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.
- */
+ *numerator = n;
+ *denominator = d;
+ return True;
+}
- for (i = 0; f[i] != 0; i++) {
- while (n % f[i] == 0 && d % f[i] == 0) {
- d /= f[i];
- n /= f[i];
- }
- }
+static GLboolean RRGetMscRate(struct glx_screen *psc, int32_t *numerator, int32_t *denominator)
+{
+ GLboolean ret = False;
+#ifdef XRANDR
+ Window root = RootWindow(psc->dpy, psc->scr);
+ XRRScreenResources *res;
+ int rr_event, rr_error;
+ RROutput primary;
+ RRMode mode = 0;
+ int n;
+
+ if (!XRRQueryExtension(psc->dpy, &rr_event, &rr_error))
+ return ret;
+
+ res = XRRGetScreenResourcesCurrent(psc->dpy, root);
+ if (res == NULL)
+ return ret;
+
+ /* Use the primary output if specified, otherwise
+ * use the mode on the first enabled crtc.
+ */
+ primary = XRRGetOutputPrimary(psc->dpy, root);
+ if (primary) {
+ XRROutputInfo *output;
+
+ output = XRRGetOutputInfo(psc->dpy, res, primary);
+ if (output != NULL) {
+ if (output->crtc) {
+ XRRCrtcInfo *crtc;
+
+ crtc = XRRGetCrtcInfo(psc->dpy, res, output->crtc);
+ if (crtc) {
+ mode = crtc->mode;
+ XRRFreeCrtcInfo(crtc);
+ }
+ }
+ XRRFreeOutputInfo(output);
}
+ }
- *numerator = n;
- *denominator = d;
+ for (n = 0; mode == 0 && n < res->ncrtc; n++) {
+ XRRCrtcInfo *crtc;
- return True;
+ crtc = XRRGetCrtcInfo(psc->dpy, res, res->crtcs[n]);
+ if (crtc) {
+ mode = crtc->mode;
+ XRRFreeCrtcInfo(crtc);
+ }
}
- else
+
+ 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);
+#endif
+ return ret;
+}
+
+static GLboolean VMGetMscRate(struct glx_screen *psc, int32_t *numerator, int32_t *denominator)
+{
+#ifdef XF86VIDMODE
+ XF86VidModeModeLine mode_line;
+ int dot_clock;
+ int i;
+
+ if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
+ XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line))
+ return compute_refresh_rate_from_mode(dot_clock * 1000,
+ mode_line.vtotal * mode_line.htotal,
+ mode_line.flags,
+ numerator,
+ denominator);
#endif
return False;
}
+
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+_X_HIDDEN GLboolean
+__glxGetMscRate(struct glx_screen *psc,
+ int32_t * numerator, int32_t * denominator)
+{
+ if (RRGetMscRate(psc, numerator, denominator))
+ return True;
+
+ if (VMGetMscRate(psc, numerator, denominator))
+ return True;
+
+ return False;
+}
#endif
/**
--
2.0.0.rc2
More information about the mesa-dev
mailing list