This is an automated email from the git hooks/post-receive script. olivier pushed a commit to branch master in repository xfce/xfwm4.
commit 8fbff6ce0c097897a1f909dd02f72f4160f23d99 Author: Olivier Fourdan <four...@xfce.org> Date: Tue Mar 24 21:04:17 2015 +0100 Implement vsync using OpenGL Bug: 11642 Signed-off-by: Olivier Fourdan <four...@xfce.org> --- configure.ac.in | 10 +- settings-dialogs/tweaks-settings.c | 2 +- src/Makefile.am | 3 +- src/compositor.c | 357 +++++++++++++----------------------- src/screen.h | 25 +-- 5 files changed, 149 insertions(+), 248 deletions(-) diff --git a/configure.ac.in b/configure.ac.in index af7084b..6d72221 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -19,7 +19,7 @@ m4_define([xcomposite_minimum_version], [0.2]) m4_define([wnck_minimum_version], [2.22]) m4_define([startup_notification_minimum_version], [0.5]) m4_define([intltool_minimum_version], [0.31]) -m4_define([libdrm_minimum_version], [2.4]) +m4_define([libepoxy_minimum_version], [1.0]) dnl init autoconf AC_COPYRIGHT([Copyright (c) 2002-2014 @@ -99,10 +99,10 @@ XDT_CHECK_PACKAGE([DBUS_GLIB], [dbus-glib-1], [0.72]) dnl dnl Sync to vblank support dnl -XDT_CHECK_OPTIONAL_PACKAGE([LIBDRM], - [libdrm], [libdrm_minimum_version], - [libdrm], - [userspace interface to the kernel DRM services], [yes]) +XDT_CHECK_OPTIONAL_PACKAGE([EPOXY], + [epoxy], [libepoxy_minimum_version], + [epoxy], + [library for handling OpenGL function pointer management], [yes]) dnl dnl Startup notification support diff --git a/settings-dialogs/tweaks-settings.c b/settings-dialogs/tweaks-settings.c index 8585c53..7c4f1f7 100644 --- a/settings-dialogs/tweaks-settings.c +++ b/settings-dialogs/tweaks-settings.c @@ -399,7 +399,7 @@ wm_tweaks_dialog_configure_widgets (GtkBuilder *builder) "/general/unredirect_overlays", G_TYPE_BOOLEAN, (GObject *)unredirect_overlays_check, "active"); -#ifdef HAVE_LIBDRM +#ifdef HAVE_EPOXY xfconf_g_property_bind (xfwm4_channel, "/general/sync_to_vblank", G_TYPE_BOOLEAN, diff --git a/src/Makefile.am b/src/Makefile.am index ee2fff6..03649ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -80,9 +80,9 @@ xfwm4_CFLAGS = \ $(LIBXFCE4UI_CFLAGS) \ $(LIBXFCE4KBD_PRIVATE_CFLAGS) \ $(RENDER_CFLAGS) \ - $(LIBDRM_CFLAGS) \ $(LIBSTARTUP_NOTIFICATION_CFLAGS) \ $(COMPOSITOR_CFLAGS) \ + $(EPOXY_CFLAGS) \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ -DDATADIR=\"$(datadir)\" \ -DHELPERDIR=\"$(HELPER_PATH_PREFIX)\" \ @@ -102,6 +102,7 @@ xfwm4_LDADD = \ $(RENDER_LIBS) \ $(COMPOSITOR_LIBS) \ $(RANDR_LIBS) \ + $(EPOXY_LIBS) \ $(MATH_LIBS) EXTRA_DIST = \ diff --git a/src/compositor.c b/src/compositor.c index 56e41b3..306a9ef 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -37,15 +37,10 @@ #include <string.h> #include <libxfce4util/libxfce4util.h> -#ifdef HAVE_LIBDRM -#include <stdint.h> -#include <fcntl.h> -#include <errno.h> -#include <drm.h> -#ifdef HAVE_STROPTS_H -#include <stropts.h> -#endif -#endif /* HAVE_LIBDRM */ +#ifdef HAVE_EPOXY +#include <epoxy/gl.h> +#include <epoxy/glx.h> +#endif /* HAVE_EPOXY */ #include "display.h" #include "screen.h" @@ -97,15 +92,6 @@ /* Set TIMEOUT_REPAINT to 0 to disable timeout repaint */ #define TIMEOUT_REPAINT 10 /* msec */ -#define TIMEOUT_REPAINT_MIN 1 -#define TIMEOUT_REPAINT_MAX 20 -#define TIMEOUT_DRI 10 /* seconds */ - -#ifdef __OpenBSD__ -#define DRM_CARD0 "/dev/drm0" -#else -#define DRM_CARD0 "/dev/dri/card0" -#endif typedef struct _CWindow CWindow; struct _CWindow @@ -1282,112 +1268,136 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part) } } -#if HAVE_LIBDRM -#if TIMEOUT_REPAINT - -static void -open_dri (ScreenInfo *screen_info) -{ - screen_info->dri_fd = open (DRM_CARD0, O_RDWR); - if (screen_info->dri_fd == -1) - { - g_warning ("Error opening %s: %s", DRM_CARD0, g_strerror (errno)); - } -} - -static void -close_dri (ScreenInfo *screen_info) -{ - if (screen_info->dri_fd != -1) - { - close (screen_info->dri_fd); - screen_info->dri_fd = -1; - } -} - +#if HAVE_EPOXY static gboolean -dri_enabled (ScreenInfo *screen_info) +vblank_enabled (ScreenInfo *screen_info) { - return (screen_info->dri_fd != -1 && screen_info->params->sync_to_vblank); + return (screen_info->params->sync_to_vblank && + (screen_info->has_glx_video_sync || screen_info->has_glx_sync_control)); } -static void -wait_vblank (ScreenInfo *screen_info) -{ - int retval; - drm_wait_vblank_t vblank; +static gboolean +vblank_init(ScreenInfo *screen_info) +{ + static int visual_attribs[] = { + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + None + }; + int version; + int n_configs; + int i; + GLXFBConfig* configs, fb_config; + gboolean fb_match; + VisualID xvisual_id; + + version = epoxy_glx_version (myScreenGetXDisplay (screen_info), screen_info->screen); + if (version < 13) + { + g_warning ("GLX version %d is too old, vsync disabled."); + return FALSE; + } - if (screen_info->dri_time > g_get_monotonic_time()) + configs = glXChooseFBConfig(myScreenGetXDisplay (screen_info), + screen_info->screen, + visual_attribs, + &n_configs); + if (configs == NULL) { - return; + g_warning ("Cannot retrieve frame buffer config, vsync disabled."); + return FALSE; } - vblank.request.sequence = 1; - vblank.request.type = _DRM_VBLANK_RELATIVE; - if (screen_info->dri_secondary) + fb_match = FALSE; + xvisual_id = XVisualIDFromVisual (screen_info->visual); + for (i = 0; i < n_configs; i++) { - vblank.request.type |= _DRM_VBLANK_SECONDARY; + XVisualInfo *visual_info; + + visual_info = glXGetVisualFromFBConfig (myScreenGetXDisplay (screen_info), + configs[i]); + if (visual_info == NULL) + { + continue; + } + if (visual_info->visualid == xvisual_id) + { + fb_config = configs[i]; + fb_match = TRUE; + XFree (visual_info); + break; + } + + XFree (visual_info); } + XFree(configs); - do + if (fb_match == FALSE) { - retval = ioctl (screen_info->dri_fd, DRM_IOCTL_WAIT_VBLANK, &vblank); - vblank.request.type &= ~_DRM_VBLANK_RELATIVE; + g_warning ("Cannot find a matching visual for the frame buffer config, vsync disabled."); + return FALSE; } - while (retval == -1 && errno == EINTR); - screen_info->vblank_time = g_get_monotonic_time (); + screen_info->has_glx_sync_control = + epoxy_has_glx_extension (myScreenGetXDisplay (screen_info), + screen_info->screen, + "GLX_OML_sync_control"); + + screen_info->has_glx_video_sync = + epoxy_has_glx_extension (myScreenGetXDisplay (screen_info), + screen_info->screen, + "GLX_SGI_video_sync"); - if (retval == -1) + if (!screen_info->has_glx_video_sync && !screen_info->has_glx_sync_control) { - if (screen_info->dri_success) - { - screen_info->dri_success = FALSE; - g_warning ("Error waiting on vblank with DRI: %s", g_strerror (errno)); - } + g_warning ("Screen is missing required GLX extension, vsync disabled."); + return FALSE; + } - /* if getting the vblank fails, try to get it from the other output */ - screen_info->dri_secondary = !screen_info->dri_secondary; + screen_info->glx_context = glXCreateNewContext(myScreenGetXDisplay (screen_info), + fb_config, + GLX_RGBA_TYPE, + 0, + TRUE); - /* the output that we tried to get the vblank from might be disabled, - if that's the case, the device needs to be reopened, or it will continue to fail */ - close_dri (screen_info); - open_dri (screen_info); + screen_info->glx_window = glXCreateWindow (myScreenGetXDisplay (screen_info), + fb_config, + screen_info->output, + NULL); - /* retry in 10 seconds */ - screen_info->dri_time = g_get_monotonic_time() + TIMEOUT_DRI * 1000000; - } - else if (!screen_info->dri_success) - { - g_message ("Using vertical blank of %s DRI output", - screen_info->dri_secondary ? "secondary" : "primary"); + glXMakeContextCurrent (myScreenGetXDisplay (screen_info), + screen_info->glx_window, + screen_info->glx_window, + screen_info->glx_context); - screen_info->dri_success = TRUE; - } + return TRUE; } -#endif /* TIMEOUT_REPAINT */ - -#endif /* HAVE_LIBDRM */ - -#ifdef HAVE_RANDR static void -get_refresh_rate (ScreenInfo* screen_info) +wait_vblank (ScreenInfo *screen_info) { - gint refresh_rate; - XRRScreenConfiguration* randr_info; + guint32 current_count; + GLXDrawable drawable; - randr_info = XRRGetScreenInfo (screen_info->display_info->dpy, screen_info->xroot); - refresh_rate = XRRConfigCurrentRate (randr_info); - XRRFreeScreenConfigInfo (randr_info); + if (screen_info->has_glx_sync_control) + { + gint64 ust, msc, sbc; - if (refresh_rate != screen_info->refresh_rate) + glXGetSyncValuesOML (myScreenGetXDisplay (screen_info), + screen_info->glx_window, + &ust, &msc, &sbc); + glXWaitForMscOML (myScreenGetXDisplay (screen_info), + screen_info->glx_window, + 0, 2, (msc + 1) % 2, + &ust, &msc, &sbc); + } + else if (screen_info->has_glx_video_sync) { - DBG ("Detected refreshrate: %i hertz", refresh_rate); - screen_info->refresh_rate = refresh_rate; + glXGetVideoSyncSGI (¤t_count); + glXWaitVideoSyncSGI (2, (current_count + 1) % 2, ¤t_count); } } -#endif /* HAVE_RANDR */ +#endif /* HAVE_EPOXY */ static void paint_all (ScreenInfo *screen_info, XserverRegion region) @@ -1400,12 +1410,6 @@ paint_all (ScreenInfo *screen_info, XserverRegion region) gint screen_height; CWindow *cw; -#ifdef HAVE_LIBDRM -#if TIMEOUT_REPAINT - gboolean use_dri; -#endif /* TIMEOUT_REPAINT */ -#endif /* HAVE_LIBDRM */ - TRACE ("entering paint_all"); g_return_if_fail (screen_info); @@ -1566,32 +1570,17 @@ paint_all (ScreenInfo *screen_info, XserverRegion region) /* Set clipping back to the given region */ XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, region); } -#ifdef HAVE_LIBDRM -#if TIMEOUT_REPAINT - use_dri = dri_enabled (screen_info); - - if (use_dri) +#ifdef HAVE_EPOXY + if (vblank_enabled (screen_info)) { - /* sync all previous rendering commands, tell xlib to render the pixmap - * onto the root window, wait for the vblank, then flush, this minimizes - * tearing*/ XFlush (dpy); + wait_vblank (screen_info); } -#endif /* TIMEOUT_REPAINT */ -#endif /* HAVE_LIBDRM */ +#endif /* HAVE_EPOXY */ XRenderComposite (dpy, PictOpSrc, screen_info->rootBuffer, None, screen_info->rootPicture, 0, 0, 0, 0, 0, 0, screen_width, screen_height); - -#ifdef HAVE_LIBDRM -#if TIMEOUT_REPAINT - if (use_dri) - { - wait_vblank (screen_info); - XFlush (dpy); - } -#endif /* TIMEOUT_REPAINT */ -#endif /* HAVE_LIBDRM */ + XFlush (dpy); XFixesDestroyRegion (dpy, paint_region); } @@ -1652,57 +1641,9 @@ static void add_repair (ScreenInfo *screen_info) { #if TIMEOUT_REPAINT -#ifdef HAVE_LIBDRM - gint64 interval; -#endif /* HAVE_LIBDRM */ - - if (screen_info->compositor_timeout_id != 0) - { - return; - } - -#ifdef HAVE_LIBDRM - if (dri_enabled (screen_info)) - { - /* schedule the next render to be half a refresh period after the last vertical blank, - but at least 1 ms in the future so that all queued events can be processed, - and to reduce latency if we didn't render for a while */ -#ifdef HAVE_RANDR - if (screen_info->refresh_rate > 0) - { - interval = (screen_info->vblank_time + 500000 / screen_info->refresh_rate - - g_get_monotonic_time ()) / 1000; - } - else -#endif /* HAVE_RANDR */ - { - interval = TIMEOUT_REPAINT - ((g_get_monotonic_time () - screen_info->vblank_time) / 1000); - } - - if (interval > TIMEOUT_REPAINT_MAX) - { - interval = TIMEOUT_REPAINT_MAX; - } - else if (interval < TIMEOUT_REPAINT_MIN) - { - interval = TIMEOUT_REPAINT_MIN; - } - } - else - { - interval = TIMEOUT_REPAINT; - } -#endif /* HAVE_LIBDRM */ - screen_info->compositor_timeout_id = -#ifdef HAVE_LIBDRM - g_timeout_add (interval, - compositor_timeout_cb, screen_info); -#else g_timeout_add (TIMEOUT_REPAINT, compositor_timeout_cb, screen_info); -#endif /*HAVE_LIBDRM */ - #endif /* TIMEOUT_REPAINT */ } @@ -2844,25 +2785,6 @@ compositorHandleShapeNotify (DisplayInfo *display_info, XShapeEvent *ev) } } -#ifdef HAVE_RANDR -static void -compositorHandleRandrNotify (DisplayInfo *display_info, XRRScreenChangeNotifyEvent *ev) -{ - ScreenInfo *screen_info; - - g_return_if_fail (display_info != NULL); - g_return_if_fail (ev != NULL); - TRACE ("entering compositorHandleRandrNotify for 0x%lx", ev->window); - - screen_info = myDisplayGetScreenFromRoot (display_info, ev->window); - if (screen_info) - { - get_refresh_rate (screen_info); - } - /* No need for RRUpdateConfiguration() here, leave that to gtk+ */ -} -#endif /* HAVE_RANDR */ - static gboolean compositorCheckCMSelection (ScreenInfo *screen_info) { @@ -3266,12 +3188,6 @@ compositorHandleEvent (DisplayInfo *display_info, XEvent *ev) { compositorHandleShapeNotify (display_info, (XShapeEvent *) ev); } -#ifdef HAVE_RANDR - else if (ev->type == (display_info->xrandr_event_base + RRScreenChangeNotify)) - { - compositorHandleRandrNotify (display_info, (XRRScreenChangeNotifyEvent *) ev); - } -#endif /* HAVE_RANDR */ #if TIMEOUT_REPAINT == 0 repair_display (display_info); @@ -3297,14 +3213,6 @@ compositorZoomIn (ScreenInfo *screen_info, XButtonEvent *ev) if (!screen_info->zoom_timeout_id) { int timeout_rate = 30; /* per second */ -#ifdef HAVE_RANDR - if (screen_info->display_info->have_xrandr) - { - timeout_rate = screen_info->refresh_rate / 2; - if (timeout_rate < 1) - timeout_rate = 30; - } -#endif /* HAVE_RANDR */ screen_info->zoom_timeout_id = g_timeout_add ((1000 / timeout_rate), zoom_timeout_cb, screen_info); } @@ -3543,21 +3451,11 @@ compositorManageScreen (ScreenInfo *screen_info) XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE); TRACE ("Manual compositing enabled"); -#ifdef HAVE_LIBDRM - open_dri (screen_info); - screen_info->dri_success = TRUE; - screen_info->dri_secondary = FALSE; - screen_info->dri_time = 0; - screen_info->vblank_time = 0; - -#ifdef HAVE_RANDR - if (display_info->have_xrandr) - { - get_refresh_rate(screen_info); - XRRSelectInput(display_info->dpy, screen_info->xroot, RRScreenChangeNotifyMask); - } -#endif /* HAVE_RANDR */ -#endif /* HAVE_LIBDRM */ +#ifdef HAVE_EPOXY + screen_info->glx_context = None; + screen_info->glx_window = None; + vblank_init (screen_info); +#endif /* HAVE_EPOXY */ return TRUE; #else @@ -3643,6 +3541,19 @@ compositorUnmanageScreen (ScreenInfo *screen_info) g_free (screen_info->gaussianMap); screen_info->gaussianMap = NULL; } +#ifdef HAVE_EPOXY + if (screen_info->glx_context) + { + glXDestroyContext (display_info->dpy, screen_info->glx_context); + screen_info->glx_context = None; + } + + if (screen_info->glx_window) + { + glXDestroyWindow (display_info->dpy, screen_info->glx_window); + screen_info->glx_window = None; + } +#endif /* HAVE_EPOXY */ screen_info->gaussianSize = -1; screen_info->wins_unredirected = 0; @@ -3651,18 +3562,6 @@ compositorUnmanageScreen (ScreenInfo *screen_info) display_info->composite_mode); compositorSetCMSelection (screen_info, None); - -#ifdef HAVE_LIBDRM - close_dri (screen_info); - -#ifdef HAVE_RANDR - if (display_info->have_xrandr) - { - XRRSelectInput (display_info->dpy, screen_info->xroot, 0); - } -#endif /* HAVE_RANDR */ -#endif /* HAVE_LIBDRM */ - #endif /* HAVE_COMPOSITOR */ } diff --git a/src/screen.h b/src/screen.h index 9aeffc4..596dafa 100644 --- a/src/screen.h +++ b/src/screen.h @@ -32,12 +32,18 @@ #include <xfconf/xfconf.h> #include <libxfce4kbd-private/xfce-shortcuts-provider.h> - #ifdef HAVE_LIBSTARTUP_NOTIFICATION #define SN_API_NOT_YET_FROZEN #include <libsn/sn.h> #endif +#ifdef HAVE_COMPOSITOR +#ifdef HAVE_EPOXY +#include <epoxy/gl.h> +#include <epoxy/glx.h> +#endif /* HAVE_EPOXY */ +#endif /* HAVE_COMPOSITOR */ + #ifndef INC_SCREEN_H #define INC_SCREEN_H @@ -188,17 +194,12 @@ struct _ScreenInfo gboolean zoomed; guint zoom_timeout_id; -#ifdef HAVE_LIBDRM - gint dri_fd; - gboolean dri_secondary; - gboolean dri_success; - gint64 dri_time; - gint64 vblank_time; -#endif /* HAVE_LIBDRM */ - -#ifdef HAVE_RANDR - gint refresh_rate; -#endif /* HAVE_RANDR */ +#ifdef HAVE_EPOXY + gboolean has_glx_sync_control; + gboolean has_glx_video_sync; + GLXContext glx_context; + GLXWindow glx_window; +#endif /* HAVE_EPOXY */ #endif /* HAVE_COMPOSITOR */ }; -- To stop receiving notification emails like this one, please contact the administrator of this repository. _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits