[Xfce4-commits] [xfce/xfwm4] 01/02: compositor: Add support for DRI3/Present
noreply at xfce.org
noreply at xfce.org
Fri Apr 24 22:33:54 CEST 2015
This is an automated email from the git hooks/post-receive script.
olivier pushed a commit to branch master
in repository xfce/xfwm4.
commit ae32b1c8dca527e117d3c373517a6941bd4c2e98
Author: Olivier Fourdan <fourdan at xfce.org>
Date: Wed Feb 25 23:10:28 2015 +0100
compositor: Add support for DRI3/Present
Bug: 11126
Make use of the newly released libXpresent library to add support for
DRI3/Present to the compositor using double-buffering.
This makes the compositor tear-free on supported hardware.
Signed-off-by: Olivier Fourdan <fourdan at xfce.org>
---
configure.ac.in | 23 +-
src/Makefile.am | 35 +--
src/compositor.c | 751 ++++++++++++++++++++++++++++++++++++------------------
src/display.h | 7 +
src/main.c | 6 +
src/screen.h | 11 +-
6 files changed, 560 insertions(+), 273 deletions(-)
diff --git a/configure.ac.in b/configure.ac.in
index 9bec579..7dc7d59 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -20,9 +20,10 @@ m4_define([wnck_minimum_version], [2.22])
m4_define([startup_notification_minimum_version], [0.5])
m4_define([intltool_minimum_version], [0.35])
m4_define([libepoxy_minimum_version], [1.0])
+m4_define([xpresent_minimum_version], [1.0])
dnl init autoconf
-AC_COPYRIGHT([Copyright (c) 2002-2014
+AC_COPYRIGHT([Copyright (c) 2002-2015
The Xfce development team. All rights reserved.
Written for Xfce by Olivier Fourdan <fourdan at xfce.org>.])
@@ -176,6 +177,7 @@ if test x"$enable_randr" = x"yes"; then
AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
[AC_CHECK_HEADER(X11/extensions/Xrandr.h,
RANDR_LIBS="-lXrandr -lXrender"
+
AC_DEFINE([HAVE_RANDR], [1], [Define to enable xrandr])
have_xrandr="yes",,
[#include <X11/Xlib.h>])],,
@@ -186,6 +188,24 @@ fi
AC_SUBST([RANDR_LIBS])
dnl
+dnl XPresent support
+dnl
+AC_ARG_ENABLE([xpresent],
+AC_HELP_STRING([--enable-xpresent], [try to use the xpresent extension])
+AC_HELP_STRING([--disable-render], [don't try to use the xpresent extension]),
+ [], [enable_xpresent=yes])
+have_xpresent="no"
+XPRESENT_LIBS=
+if test x"$enable_xpresent" = x"yes"; then
+ if $PKG_CONFIG --print-errors --exists xpresent 2>&1; then
+ PKG_CHECK_MODULES(PRESENT_EXTENSION, xpresent)
+ have_xpresent="yes"
+ AC_DEFINE([HAVE_PRESENT_EXTENSION], [1], [Define to enable xpresent])
+ fi
+fi
+AC_SUBST([PRESENT_EXTENSION_LIBS])
+
+dnl
dnl Xcomposite and related extensions
dnl
compositor="no"
@@ -261,6 +281,7 @@ echo " Startup notification support: $LIBSTARTUP_NOTIFICATION_FOUND"
echo " XSync support: $have_xsync"
echo " Render support: $have_render"
echo " Xrandr support: $have_xrandr"
+echo " Xpresent support: $have_xpresent"
echo " Embedded compositor: $compositor"
echo " Epoxy support: $EPOXY_FOUND"
echo " KDE systray protocol proxy: $kde_systray"
diff --git a/src/Makefile.am b/src/Makefile.am
index 03649ca..767b643 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -72,17 +72,19 @@ xfwm4_SOURCES = \
xpm-color-table.h
xfwm4_CFLAGS = \
- $(GTK_CFLAGS) \
$(GLIB_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(COMPOSITOR_CFLAGS) \
+ $(EPOXY_CFLAGS) \
+ $(LIBSTARTUP_NOTIFICATION_CFLAGS) \
$(LIBX11_CFLAGS) \
- $(LIBXFCONF_CFLAGS) \
- $(LIBXFCE4UTIL_CFLAGS) \
- $(LIBXFCE4UI_CFLAGS) \
$(LIBXFCE4KBD_PRIVATE_CFLAGS) \
+ $(LIBXFCE4UI_CFLAGS) \
+ $(LIBXFCE4UTIL_CFLAGS) \
+ $(LIBXFCONF_CFLAGS) \
+ $(PRESENT_EXTENSION_CFLAGS) \
+ $(RANDR_CFLAGS) \
$(RENDER_CFLAGS) \
- $(LIBSTARTUP_NOTIFICATION_CFLAGS) \
- $(COMPOSITOR_CFLAGS) \
- $(EPOXY_CFLAGS) \
-DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
-DDATADIR=\"$(datadir)\" \
-DHELPERDIR=\"$(HELPER_PATH_PREFIX)\" \
@@ -90,19 +92,20 @@ xfwm4_CFLAGS = \
-DG_LOG_DOMAIN=\"xfwm4\"
xfwm4_LDADD = \
- $(GTK_LIBS) \
$(GLIB_LIBS) \
- $(LIBX11_LIBS) \
+ $(GTK_LIBS) \
+ $(COMPOSITOR_LIBS) \
+ $(EPOXY_LIBS) \
+ $(LIBSTARTUP_NOTIFICATION_LIBS) \
$(LIBX11_LDFLAGS) \
- $(LIBXFCONF_LIBS) \
- $(LIBXFCE4UTIL_LIBS) \
- $(LIBXFCE4UI_LIBS) \
+ $(LIBX11_LIBS) \
$(LIBXFCE4KBD_PRIVATE_LIBS) \
- $(LIBSTARTUP_NOTIFICATION_LIBS) \
- $(RENDER_LIBS) \
- $(COMPOSITOR_LIBS) \
+ $(LIBXFCE4UI_LIBS) \
+ $(LIBXFCE4UTIL_LIBS) \
+ $(LIBXFCONF_LIBS) \
+ $(PRESENT_EXTENSION_LIBS) \
$(RANDR_LIBS) \
- $(EPOXY_LIBS) \
+ $(RENDER_LIBS) \
$(MATH_LIBS)
EXTRA_DIST = \
diff --git a/src/compositor.c b/src/compositor.c
index 802e7a7..75d5ce2 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -42,6 +42,10 @@
#include <epoxy/glx.h>
#endif /* HAVE_EPOXY */
+#ifdef HAVE_PRESENT_EXTENSION
+#include <X11/extensions/Xpresent.h>
+#endif /* HAVE_PRESENT_EXTENSION */
+
#include "display.h"
#include "screen.h"
#include "client.h"
@@ -50,7 +54,6 @@
#include "compositor.h"
#ifdef HAVE_COMPOSITOR
-
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
@@ -886,40 +889,43 @@ root_tile (ScreenInfo *screen_info)
return picture;
}
+static Pixmap
+create_root_pixmap (ScreenInfo *screen_info)
+{
+ Pixmap pixmap;
+ gint depth;
+
+ depth = DefaultDepth (myScreenGetXDisplay (screen_info),
+ screen_info->screen);
+
+ pixmap = XCreatePixmap (myScreenGetXDisplay (screen_info),
+ screen_info->xroot,
+ screen_info->width,
+ screen_info->height, depth);
+
+ return pixmap;
+}
+
static Picture
-create_root_buffer (ScreenInfo *screen_info)
+create_root_buffer (ScreenInfo *screen_info, Pixmap pixmap)
{
DisplayInfo *display_info;
Picture pict;
XRenderPictFormat *format;
- Pixmap rootPixmap;
Visual *visual;
- gint depth;
- gint screen_width;
- gint screen_height;
- gint screen_number;
g_return_val_if_fail (screen_info != NULL, None);
+ g_return_val_if_fail (pixmap != None, None);
TRACE ("entering create_root_buffer");
display_info = screen_info->display_info;
- screen_width = screen_info->width;
- screen_height = screen_info->height;
- screen_number = screen_info->screen;
- visual = DefaultVisual (display_info->dpy, screen_number);
- depth = DefaultDepth (display_info->dpy, screen_number);
+ visual = DefaultVisual (display_info->dpy, screen_info->screen);
format = XRenderFindVisualFormat (display_info->dpy, visual);
g_return_val_if_fail (format != NULL, None);
- rootPixmap = XCreatePixmap (display_info->dpy,
- screen_info->output,
- screen_width, screen_height, depth);
- g_return_val_if_fail (rootPixmap != None, None);
-
pict = XRenderCreatePicture (display_info->dpy,
- rootPixmap, format, 0, NULL);
- XFreePixmap (display_info->dpy, rootPixmap);
+ pixmap, format, 0, NULL);
return pict;
}
@@ -983,28 +989,148 @@ cursor_to_picture (ScreenInfo *screen_info, XFixesCursorImage *cursor)
return picture;
}
+#if HAVE_EPOXY
+static gboolean
+vblank_enabled (ScreenInfo *screen_info)
+{
+ return (screen_info->params->sync_to_vblank &&
+ (screen_info->has_glx_video_sync || screen_info->has_glx_sync_control));
+}
+
+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.", version);
+ return FALSE;
+ }
+
+ configs = glXChooseFBConfig(myScreenGetXDisplay (screen_info),
+ screen_info->screen,
+ visual_attribs,
+ &n_configs);
+ if (configs == NULL)
+ {
+ g_warning ("Cannot retrieve frame buffer config, vsync disabled.");
+ return FALSE;
+ }
+
+ fb_match = FALSE;
+ xvisual_id = XVisualIDFromVisual (screen_info->visual);
+ for (i = 0; i < n_configs; i++)
+ {
+ 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);
+
+ if (fb_match == FALSE)
+ {
+ g_warning ("Cannot find a matching visual for the frame buffer config, vsync disabled.");
+ return FALSE;
+ }
+
+ 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 (!screen_info->has_glx_video_sync && !screen_info->has_glx_sync_control)
+ {
+ g_warning ("Screen is missing required GLX extension, vsync disabled.");
+ return FALSE;
+ }
+
+ screen_info->glx_context = glXCreateNewContext(myScreenGetXDisplay (screen_info),
+ fb_config,
+ GLX_RGBA_TYPE,
+ 0,
+ TRUE);
+
+ screen_info->glx_window = glXCreateWindow (myScreenGetXDisplay (screen_info),
+ fb_config,
+ screen_info->output,
+ NULL);
+
+ glXMakeContextCurrent (myScreenGetXDisplay (screen_info),
+ screen_info->glx_window,
+ screen_info->glx_window,
+ screen_info->glx_context);
+
+ return TRUE;
+}
+
+/* Following routine is taken from gdk GL context code by Alexander Larsson */
static void
-paint_root (ScreenInfo *screen_info)
+wait_vblank (ScreenInfo *screen_info)
{
- DisplayInfo *display_info;
+ guint32 current_count;
- g_return_if_fail (screen_info != NULL);
- g_return_if_fail (screen_info->rootBuffer != None);
+ if (screen_info->has_glx_sync_control)
+ {
+ gint64 ust, msc, sbc;
- TRACE ("entering paint_root");
- if (screen_info->rootTile == None)
+ 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)
{
- screen_info->rootTile = root_tile (screen_info);
- g_return_if_fail (screen_info->rootTile != None);
+ glXGetVideoSyncSGI (¤t_count);
+ glXWaitVideoSyncSGI (2, (current_count + 1) % 2, ¤t_count);
}
+}
+#endif /* HAVE_EPOXY */
- display_info = screen_info->display_info;
- XRenderComposite (display_info->dpy, PictOpSrc,
- screen_info->rootTile, None, screen_info->rootBuffer,
- 0, 0, 0, 0, 0, 0,
- screen_info->width,
- screen_info->height);
+#ifdef HAVE_PRESENT_EXTENSION
+static void
+present_flip (ScreenInfo *screen_info, XserverRegion region, Pixmap pixmap)
+{
+ static guint32 present_serial;
+
+ XPresentPixmap (myScreenGetXDisplay (screen_info), screen_info->output,
+ pixmap, present_serial++, None, region, 0, 0, None, None, None,
+ PresentOptionNone, 0, 1, 0, NULL, 0);
}
+#endif /* HAVE_PRESENT_EXTENSION */
static XserverRegion
win_extents (CWindow *cw)
@@ -1198,7 +1324,45 @@ unredirect_win (CWindow *cw)
}
static void
-paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
+paint_root (ScreenInfo *screen_info, Picture paint_buffer)
+{
+ g_return_if_fail (screen_info != NULL);
+ g_return_if_fail (paint_buffer != None);
+
+ TRACE ("entering paint_root");
+ if (screen_info->rootTile == None)
+ {
+ screen_info->rootTile = root_tile (screen_info);
+ g_return_if_fail (screen_info->rootTile != None);
+ }
+
+ XRenderComposite (myScreenGetXDisplay (screen_info),
+ PictOpSrc,
+ screen_info->rootTile,
+ None, paint_buffer,
+ 0, 0, 0, 0, 0, 0,
+ screen_info->width,
+ screen_info->height);
+}
+
+static void
+paint_cursor (ScreenInfo *screen_info, XserverRegion region, Picture paint_buffer)
+{
+ XFixesSetPictureClipRegion (myScreenGetXDisplay (screen_info),
+ paint_buffer, 0, 0, region);
+ XRenderComposite (myScreenGetXDisplay (screen_info),
+ PictOpOver,
+ screen_info->cursorPicture,
+ None, paint_buffer,
+ 0, 0, 0, 0,
+ screen_info->cursorLocation.x,
+ screen_info->cursorLocation.y,
+ screen_info->cursorLocation.width,
+ screen_info->cursorLocation.height);
+}
+
+static void
+paint_win (CWindow *cw, XserverRegion region, Picture paint_buffer, gboolean solid_part)
{
ScreenInfo *screen_info;
DisplayInfo *display_info;
@@ -1244,7 +1408,7 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
/* Top Border (title bar) */
XRenderComposite (display_info->dpy, PictOpOver, cw->picture, cw->alphaBorderPict,
- screen_info->rootBuffer,
+ paint_buffer,
0, 0,
0, 0,
frame_x, frame_y,
@@ -1252,14 +1416,14 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
/* Bottom Border */
XRenderComposite (display_info->dpy, PictOpOver, cw->picture, cw->alphaBorderPict,
- screen_info->rootBuffer,
+ paint_buffer,
0, frame_height - frame_bottom,
0, 0,
frame_x, frame_y + frame_height - frame_bottom,
frame_width, frame_bottom);
/* Left Border */
XRenderComposite (display_info->dpy, PictOpOver, cw->picture, cw->alphaBorderPict,
- screen_info->rootBuffer,
+ paint_buffer,
0, frame_top,
0, 0,
frame_x, frame_y + frame_top,
@@ -1267,7 +1431,7 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
/* Right Border */
XRenderComposite (display_info->dpy, PictOpOver, cw->picture, cw->alphaBorderPict,
- screen_info->rootBuffer,
+ paint_buffer,
frame_width - frame_right, frame_top,
0, 0,
frame_x + frame_width - frame_right,
@@ -1280,9 +1444,9 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
XRectangle r;
XserverRegion client_region;
- XFixesSetPictureClipRegion (display_info->dpy, screen_info->rootBuffer, 0, 0, region);
+ XFixesSetPictureClipRegion (display_info->dpy, paint_buffer, 0, 0, region);
XRenderComposite (display_info->dpy, PictOpSrc, cw->picture, None,
- screen_info->rootBuffer,
+ paint_buffer,
frame_left, frame_top,
0, 0,
frame_x + frame_left, frame_y + frame_top,
@@ -1299,7 +1463,7 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
else if (!solid_part)
{
XRenderComposite (display_info->dpy, PictOpOver, cw->picture, cw->alphaPict,
- screen_info->rootBuffer,
+ paint_buffer,
frame_left, frame_top,
0, 0,
frame_x + frame_left, frame_y + frame_top,
@@ -1314,162 +1478,36 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
get_paint_bounds (cw, &x, &y, &w, &h);
if (paint_solid)
{
- XFixesSetPictureClipRegion (display_info->dpy, screen_info->rootBuffer, 0, 0, region);
- XRenderComposite (display_info->dpy, PictOpSrc, cw->picture, None, screen_info->rootBuffer,
+ XFixesSetPictureClipRegion (display_info->dpy, paint_buffer, 0, 0, region);
+ XRenderComposite (display_info->dpy, PictOpSrc,
+ cw->picture, None,
+ paint_buffer,
0, 0, 0, 0, x, y, w, h);
XFixesSubtractRegion (display_info->dpy, region, region, cw->borderSize);
}
else if (!solid_part)
{
- XRenderComposite (display_info->dpy, PictOpOver, cw->picture, cw->alphaPict, screen_info->rootBuffer,
+ XRenderComposite (display_info->dpy, PictOpOver,
+ cw->picture, cw->alphaPict,
+ paint_buffer,
0, 0, 0, 0, x, y, w, h);
}
}
}
-#if HAVE_EPOXY
-static gboolean
-vblank_enabled (ScreenInfo *screen_info)
-{
- return (screen_info->params->sync_to_vblank &&
- (screen_info->has_glx_video_sync || screen_info->has_glx_sync_control));
-}
-
-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.", version);
- return FALSE;
- }
-
- configs = glXChooseFBConfig(myScreenGetXDisplay (screen_info),
- screen_info->screen,
- visual_attribs,
- &n_configs);
- if (configs == NULL)
- {
- g_warning ("Cannot retrieve frame buffer config, vsync disabled.");
- return FALSE;
- }
-
- fb_match = FALSE;
- xvisual_id = XVisualIDFromVisual (screen_info->visual);
- for (i = 0; i < n_configs; i++)
- {
- 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);
-
- if (fb_match == FALSE)
- {
- g_warning ("Cannot find a matching visual for the frame buffer config, vsync disabled.");
- return FALSE;
- }
-
- 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 (!screen_info->has_glx_video_sync && !screen_info->has_glx_sync_control)
- {
- g_warning ("Screen is missing required GLX extension, vsync disabled.");
- return FALSE;
- }
-
- screen_info->glx_context = glXCreateNewContext(myScreenGetXDisplay (screen_info),
- fb_config,
- GLX_RGBA_TYPE,
- 0,
- TRUE);
-
- screen_info->glx_window = glXCreateWindow (myScreenGetXDisplay (screen_info),
- fb_config,
- screen_info->output,
- NULL);
-
- glXMakeContextCurrent (myScreenGetXDisplay (screen_info),
- screen_info->glx_window,
- screen_info->glx_window,
- screen_info->glx_context);
-
- return TRUE;
-}
-
-/* Following routine is taken from gdk GL context code by Alexander Larsson */
static void
-wait_vblank (ScreenInfo *screen_info)
-{
- guint32 current_count;
-
- if (screen_info->has_glx_sync_control)
- {
- gint64 ust, msc, sbc;
-
- 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)
- {
- glXGetVideoSyncSGI (¤t_count);
- glXWaitVideoSyncSGI (2, (current_count + 1) % 2, ¤t_count);
- }
-}
-#endif /* HAVE_EPOXY */
-
-static void
-paint_all (ScreenInfo *screen_info, XserverRegion region)
+paint_all (ScreenInfo *screen_info, XserverRegion region, gushort buffer)
{
DisplayInfo *display_info;
XserverRegion paint_region;
+ Picture paint_buffer;
Display *dpy;
GList *list;
gint screen_width;
gint screen_height;
CWindow *cw;
- TRACE ("entering paint_all");
+ TRACE ("entering paint_all buffer %d", buffer);
g_return_if_fail (screen_info);
display_info = screen_info->display_info;
@@ -1478,20 +1516,33 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
screen_height = screen_info->height;
/* Create root buffer if not done yet */
- if (screen_info->rootBuffer == None)
+ if (screen_info->rootPixmap[buffer] == None)
{
- screen_info->rootBuffer = create_root_buffer (screen_info);
- g_return_if_fail (screen_info->rootBuffer != None);
-
- memset(screen_info->transform.matrix, 0, 9);
- screen_info->transform.matrix[0][0] = 1 << 16;
- screen_info->transform.matrix[1][1] = 1 << 16;
- screen_info->transform.matrix[2][2] = 1 << 16;
- screen_info->zoomed = 0;
+ screen_info->rootPixmap[buffer] = create_root_pixmap (screen_info);
+ }
- XFixesShowCursor (display_info->dpy, screen_info->xroot);
+ if (screen_info->rootBuffer[buffer] == None)
+ {
+ screen_info->rootBuffer[buffer] =
+ create_root_buffer (screen_info, screen_info->rootPixmap[buffer]);
}
+ if (screen_info->zoomBuffer == None)
+ {
+ Pixmap pixmap;
+
+ pixmap = create_root_pixmap (screen_info);
+ screen_info->zoomBuffer = create_root_buffer (screen_info, pixmap);
+ XFreePixmap (display_info->dpy, pixmap);
+ }
+ if (screen_info->zoomed)
+ {
+ paint_buffer = screen_info->zoomBuffer;
+ }
+ else
+ {
+ paint_buffer = screen_info->rootBuffer[buffer];
+ }
/* Copy the original given region */
paint_region = XFixesCreateRegion (dpy, NULL, 0);
XFixesCopyRegion (dpy, paint_region, region);
@@ -1544,7 +1595,7 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
}
if (WIN_IS_OPAQUE(cw))
{
- paint_win (cw, paint_region, TRUE);
+ paint_win (cw, paint_region, paint_buffer, TRUE);
}
if (cw->borderClip == None)
{
@@ -1559,8 +1610,8 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
* region has changed because of the XFixesSubtractRegion (),
* reapply clipping for the last iteration.
*/
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, paint_region);
- paint_root (screen_info);
+ XFixesSetPictureClipRegion (dpy, paint_buffer, 0, 0, paint_region);
+ paint_root (screen_info, paint_buffer);
/*
* Painting from bottom to top, translucent windows and shadows are painted now...
@@ -1584,9 +1635,9 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
shadowClip = XFixesCreateRegion (dpy, NULL, 0);
XFixesSubtractRegion (dpy, shadowClip, cw->borderClip, cw->borderSize);
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, shadowClip);
+ XFixesSetPictureClipRegion (dpy, paint_buffer, 0, 0, shadowClip);
XRenderComposite (dpy, PictOpOver, screen_info->blackPicture, cw->shadow,
- screen_info->rootBuffer, 0, 0, 0, 0,
+ paint_buffer, 0, 0, 0, 0,
cw->attr.x + cw->shadow_dx,
cw->attr.y + cw->shadow_dy,
cw->shadow_width, cw->shadow_height);
@@ -1603,8 +1654,9 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
0.0 /* blue */);
}
XFixesIntersectRegion (dpy, cw->borderClip, cw->borderClip, cw->borderSize);
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, cw->borderClip);
- paint_win (cw, paint_region, FALSE);
+ XFixesSetPictureClipRegion (dpy, paint_buffer,
+ 0, 0, cw->borderClip);
+ paint_win (cw, paint_region, paint_buffer, FALSE);
}
if (shadowClip)
@@ -1619,86 +1671,135 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
}
}
- if (screen_info->zoomed)
- {
- TRACE ("Drawing the scaled cursor");
- if (screen_info->cursorPicture)
- {
- /* Switch back to the original region */
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, region);
- XRenderComposite (dpy, PictOpOver, screen_info->cursorPicture,
- None, screen_info->rootBuffer,
- 0, 0, 0, 0,
- screen_info->cursorLocation.x,
- screen_info->cursorLocation.y,
- screen_info->cursorLocation.width,
- screen_info->cursorLocation.height);
- }
- }
-
TRACE ("Copying data back to screen");
if (screen_info->zoomed)
{
/* Fixme: copy back whole screen if zoomed
It would be better to scale the clipping region if possible. */
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, None);
+ XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer[buffer],
+ 0, 0, None);
+ paint_cursor (screen_info, region, screen_info->zoomBuffer);
+ XFixesSetPictureClipRegion (dpy, screen_info->zoomBuffer,
+ 0, 0, None);
}
else
{
/* Set clipping back to the given region */
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, region);
+ XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer[buffer],
+ 0, 0, region);
}
-#ifdef HAVE_EPOXY
- if (vblank_enabled (screen_info))
+
+#ifdef HAVE_PRESENT_EXTENSION
+ if (display_info->have_present)
{
- XFlush (dpy);
- wait_vblank (screen_info);
+ if (screen_info->zoomed)
+ {
+ XRenderComposite (dpy, PictOpSrc,
+ screen_info->zoomBuffer,
+ None, screen_info->rootBuffer[buffer],
+ 0, 0, 0, 0, 0, 0, screen_width, screen_height);
+ }
+ present_flip (screen_info, region, screen_info->rootPixmap[buffer]);
+ screen_info->present_pending = TRUE;
}
+ else
+#endif /* HAVE_PRESENT_EXTENSION */
+ {
+#ifdef HAVE_EPOXY
+ if (vblank_enabled (screen_info))
+ {
+ XFlush (dpy);
+ wait_vblank (screen_info);
+ }
#endif /* HAVE_EPOXY */
-
- XRenderComposite (dpy, PictOpSrc, screen_info->rootBuffer, None, screen_info->rootPicture,
- 0, 0, 0, 0, 0, 0, screen_width, screen_height);
- XFlush (dpy);
+ XRenderComposite (dpy, PictOpSrc, paint_buffer,
+ None, screen_info->rootPicture,
+ 0, 0, 0, 0, 0, 0, screen_width, screen_height);
+ XFlush (dpy);
+ }
XFixesDestroyRegion (dpy, paint_region);
}
-#if TIMEOUT_REPAINT
static void
remove_timeouts (ScreenInfo *screen_info)
{
+#if TIMEOUT_REPAINT
if (screen_info->compositor_timeout_id != 0)
{
g_source_remove (screen_info->compositor_timeout_id);
screen_info->compositor_timeout_id = 0;
}
-}
#endif /* TIMEOUT_REPAINT */
+}
-static void
+static gboolean
repair_screen (ScreenInfo *screen_info)
{
DisplayInfo *display_info;
- g_return_if_fail (screen_info);
+ g_return_val_if_fail (screen_info, FALSE);
TRACE ("entering repair_screen");
if (!screen_info->compositor_active)
{
- return;
+ return FALSE;
}
-#if TIMEOUT_REPAINT
- remove_timeouts (screen_info);
-#endif /* TIMEOUT_REPAINT */
-
display_info = screen_info->display_info;
- if (screen_info->allDamage != None)
+ if (screen_info->allDamage)
{
- paint_all (screen_info, screen_info->allDamage);
- XFixesDestroyRegion (display_info->dpy, screen_info->allDamage);
- screen_info->allDamage = None;
+#ifdef HAVE_PRESENT_EXTENSION
+ if (display_info->have_present)
+ {
+ if (!screen_info->present_pending)
+ {
+ XserverRegion damage = screen_info->allDamage;
+
+ if (screen_info->prevDamage)
+ {
+ XFixesUnionRegion(display_info->dpy,
+ screen_info->prevDamage,
+ screen_info->prevDamage,
+ damage);
+ damage = screen_info->prevDamage;
+ }
+
+ remove_timeouts (screen_info);
+ paint_all (screen_info, damage, screen_info->current_buffer);
+
+ if (++screen_info->current_buffer > 1)
+ {
+ screen_info->current_buffer = 0;
+ }
+
+ if (screen_info->prevDamage)
+ {
+ XFixesDestroyRegion (display_info->dpy, screen_info->prevDamage);
+ }
+
+ screen_info->prevDamage = screen_info->allDamage;
+ screen_info->allDamage = None;
+
+ return FALSE;
+ }
+ /*
+ * We did not paint the screen because we are waiting for
+ * a pending present notification, do not cancel the callback yet...
+ */
+ return TRUE;
+ }
+ else
+#endif /* HAVE_PRESENT_EXTENSION */
+ {
+ remove_timeouts (screen_info);
+ paint_all (screen_info, screen_info->allDamage, screen_info->current_buffer);
+ XFixesDestroyRegion (display_info->dpy, screen_info->allDamage);
+ screen_info->allDamage = None;
+ }
}
+
+ return FALSE;
}
#if TIMEOUT_REPAINT
@@ -1709,9 +1810,7 @@ compositor_timeout_cb (gpointer data)
screen_info = (ScreenInfo *) data;
screen_info->compositor_timeout_id = 0;
- repair_screen (screen_info);
-
- return FALSE;
+ return repair_screen (screen_info);
}
#endif /* TIMEOUT_REPAINT */
@@ -1719,9 +1818,12 @@ static void
add_repair (ScreenInfo *screen_info)
{
#if TIMEOUT_REPAINT
- screen_info->compositor_timeout_id =
- g_timeout_add (TIMEOUT_REPAINT,
- compositor_timeout_cb, screen_info);
+ if (screen_info->compositor_timeout_id == 0)
+ {
+ screen_info->compositor_timeout_id =
+ g_timeout_add (TIMEOUT_REPAINT,
+ compositor_timeout_cb, screen_info);
+ }
#endif /* TIMEOUT_REPAINT */
}
@@ -1739,7 +1841,7 @@ repair_display (DisplayInfo *display_info)
repair_screen ((ScreenInfo *) screens->data);
}
}
-#endif
+#endif /* TIMEOUT_REPAINT == 0 */
static void
add_damage (ScreenInfo *screen_info, XserverRegion damage)
@@ -2546,11 +2648,11 @@ recenter_zoomed_area (ScreenInfo *screen_info, int x_root, int y_root)
}
if (zf > (1 << 14) && zf < (1 << 16))
- XRenderSetPictureFilter (dpy, screen_info->rootBuffer, FilterBilinear, NULL, 0);
+ XRenderSetPictureFilter (dpy, screen_info->zoomBuffer, FilterBilinear, NULL, 0);
else
- XRenderSetPictureFilter (dpy, screen_info->rootBuffer, FilterNearest, NULL, 0);
+ XRenderSetPictureFilter (dpy, screen_info->zoomBuffer, FilterNearest, NULL, 0);
- XRenderSetPictureTransform (dpy, screen_info->rootBuffer, &screen_info->transform);
+ XRenderSetPictureTransform (dpy, screen_info->zoomBuffer, &screen_info->transform);
damage_screen (screen_info);
}
@@ -2943,6 +3045,50 @@ compositorCheckCMSelection (ScreenInfo *screen_info)
return FALSE;
}
+#ifdef HAVE_PRESENT_EXTENSION
+static void
+compositorHandlePresentCompleteNotify (DisplayInfo *display_info, XPresentCompleteNotifyEvent *ev)
+{
+ ScreenInfo *screen_info;
+ GSList *list;
+
+ g_return_if_fail (display_info != NULL);
+ g_return_if_fail (ev != NULL);
+ TRACE ("entering compositorHandlePresentCompleteNotify for 0x%lx", ev->window);
+
+ for (list = display_info->screens; list; list = g_slist_next (list))
+ {
+ screen_info = (ScreenInfo *) list->data;
+ if (screen_info->output == ev->window)
+ {
+ screen_info->present_pending = FALSE;
+ break;
+ }
+ }
+}
+
+static void
+compositorHandleGenericEvent(DisplayInfo *display_info, XGenericEvent *ev)
+{
+ XGenericEventCookie *ev_cookie = (XGenericEventCookie *) ev;
+
+ g_return_if_fail (display_info != NULL);
+ g_return_if_fail (ev != NULL);
+ TRACE ("entering compositorHandleGenericEvent");
+
+ if (ev_cookie->extension == display_info->present_opcode)
+ {
+ XGetEventData (display_info->dpy, ev_cookie);
+ if (ev_cookie->evtype == PresentCompleteNotify)
+ {
+ compositorHandlePresentCompleteNotify (display_info,
+ (XPresentCompleteNotifyEvent *) ev_cookie->data);
+ }
+ XFreeEventData (display_info->dpy, ev_cookie);
+ }
+}
+#endif /* HAVE_PRESENT_EXTENSION */
+
static void
compositorSetCMSelection (ScreenInfo *screen_info, Window w)
{
@@ -3323,6 +3469,12 @@ compositorHandleEvent (DisplayInfo *display_info, XEvent *ev)
{
compositorHandleCursorNotify (display_info, (XFixesCursorNotifyEvent *) ev);
}
+#ifdef HAVE_PRESENT_EXTENSION
+ else if (ev->type == GenericEvent)
+ {
+ compositorHandleGenericEvent (display_info, (XGenericEvent *) ev);
+ }
+#endif /* HAVE_PRESENT_EXTENSION */
#if TIMEOUT_REPAINT == 0
repair_display (display_info);
@@ -3351,11 +3503,10 @@ compositorZoomIn (ScreenInfo *screen_info, XButtonEvent *ev)
screen_info->cursorLocation.x = ev->y_root - screen_info->cursorOffsetY;
}
- screen_info->zoomed = 1;
+ screen_info->zoomed = TRUE;
if (!screen_info->zoom_timeout_id)
{
- int timeout_rate = 30; /* per second */
- screen_info->zoom_timeout_id = g_timeout_add ((1000 / timeout_rate),
+ screen_info->zoom_timeout_id = g_timeout_add ((1000 / 30 /* per second */),
zoom_timeout_cb, screen_info);
}
recenter_zoomed_area (screen_info, ev->x_root, ev->y_root);
@@ -3376,9 +3527,9 @@ compositorZoomOut (ScreenInfo *screen_info, XButtonEvent *ev)
{
screen_info->transform.matrix[0][0] = (1 << 16);
screen_info->transform.matrix[1][1] = (1 << 16);
- screen_info->zoomed = 0;
screen_info->transform.matrix[0][2] = 0;
screen_info->transform.matrix[1][2] = 0;
+ screen_info->zoomed = FALSE;
XFixesShowCursor (screen_info->display_info->dpy, screen_info->xroot);
}
@@ -3449,6 +3600,28 @@ compositorInitDisplay (DisplayInfo *display_info)
DBG ("fixes error base: %i", display_info->fixes_error_base);
}
+#ifdef HAVE_PRESENT_EXTENSION
+ if (!XPresentQueryExtension (display_info->dpy,
+ &display_info->present_opcode,
+ &display_info->present_event_base,
+ &display_info->present_error_base))
+ {
+ g_warning ("The display does not support the XPresent extension.");
+ display_info->have_present = FALSE;
+ display_info->present_opcode = 0;
+ display_info->present_event_base = 0;
+ display_info->present_error_base = 0;
+ }
+ else
+ {
+ display_info->have_present = TRUE;
+
+ DBG ("present opcode: %i", display_info->present_opcode);
+ DBG ("present event base: %i", display_info->present_event_base);
+ DBG ("present error base: %i", display_info->present_error_base);
+ }
+#endif /* HAVE_PRESENT_EXTENSION */
+
display_info->enable_compositor = ((display_info->have_render)
&& (display_info->have_composite)
&& (display_info->have_damage)
@@ -3499,6 +3672,7 @@ compositorManageScreen (ScreenInfo *screen_info)
DisplayInfo *display_info;
XRenderPictureAttributes pa;
XRenderPictFormat *visual_format;
+ gushort buffer;
g_return_val_if_fail (screen_info != NULL, FALSE);
TRACE ("entering compositorManageScreen");
@@ -3575,7 +3749,6 @@ compositorManageScreen (ScreenInfo *screen_info)
screen_info->gaussianSize = -1;
screen_info->gaussianMap = make_gaussian_map(SHADOW_RADIUS);
presum_gaussian (screen_info);
- screen_info->rootBuffer = None;
screen_info->cursorPicture = None;
/* Change following argb values to play with shadow colors */
screen_info->blackPicture = solid_picture (screen_info,
@@ -3586,13 +3759,24 @@ compositorManageScreen (ScreenInfo *screen_info)
0.0 /* blue */);
screen_info->rootTile = None;
screen_info->allDamage = None;
+ screen_info->prevDamage = None;
screen_info->cwindows = NULL;
screen_info->wins_unredirected = 0;
screen_info->compositor_timeout_id = 0;
- screen_info->zoomed = 0;
+ screen_info->zoomed = FALSE;
screen_info->zoom_timeout_id = 0;
screen_info->damages_pending = FALSE;
-
+ screen_info->current_buffer = 0;
+ memset(screen_info->transform.matrix, 0, 9);
+ screen_info->transform.matrix[0][0] = 1 << 16;
+ screen_info->transform.matrix[1][1] = 1 << 16;
+ screen_info->transform.matrix[2][2] = 1 << 16;
+ screen_info->zoomBuffer = None;
+ for (buffer = 0; buffer < 2; buffer++)
+ {
+ screen_info->rootPixmap[buffer] = None;
+ screen_info->rootBuffer[buffer] = None;
+ }
XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
TRACE ("Manual compositing enabled");
@@ -3602,7 +3786,14 @@ compositorManageScreen (ScreenInfo *screen_info)
vblank_init (screen_info);
#endif /* HAVE_EPOXY */
- XFixesSelectCursorInput (screen_info->display_info->dpy,
+#ifdef HAVE_PRESENT_EXTENSION
+ screen_info->present_pending = FALSE;
+ XPresentSelectInput (display_info->dpy,
+ screen_info->output,
+ PresentCompleteNotifyMask);
+#endif /* HAVE_PRESENT_EXTENSION */
+
+ XFixesSelectCursorInput (display_info->dpy,
screen_info->xroot,
XFixesDisplayCursorNotifyMask);
@@ -3619,6 +3810,7 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
DisplayInfo *display_info;
GList *list;
gint i;
+ gushort buffer;
g_return_if_fail (screen_info != NULL);
TRACE ("entering compositorUnmanageScreen");
@@ -3662,11 +3854,44 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
}
#endif /* HAVE_OVERLAYS */
+ for (buffer = 0; buffer < 2; buffer++)
+ {
+ if (screen_info->rootPixmap[buffer])
+ {
+ XFreePixmap (display_info->dpy, screen_info->rootPixmap[buffer]);
+ screen_info->rootPixmap[buffer] = None;
+ }
+ if (screen_info->rootBuffer[buffer])
+ {
+ XRenderFreePicture (display_info->dpy, screen_info->rootBuffer[buffer]);
+ screen_info->rootBuffer[buffer] = None;
+ }
+ }
+
+ if (screen_info->allDamage)
+ {
+ XFixesDestroyRegion (display_info->dpy, screen_info->allDamage);
+ screen_info->allDamage = None;
+ }
+
+ if (screen_info->prevDamage)
+ {
+ XFixesDestroyRegion (display_info->dpy, screen_info->prevDamage);
+ screen_info->prevDamage = None;
+ }
+
+ if (screen_info->zoomBuffer)
+ {
+ XRenderFreePicture (display_info->dpy, screen_info->zoomBuffer);
+ screen_info->zoomBuffer = None;
+ }
+
if (screen_info->rootPicture)
{
XRenderFreePicture (display_info->dpy, screen_info->rootPicture);
screen_info->rootPicture = None;
}
+
if (screen_info->blackPicture)
{
XRenderFreePicture (display_info->dpy, screen_info->blackPicture);
@@ -3695,6 +3920,7 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
g_free (screen_info->gaussianMap);
screen_info->gaussianMap = NULL;
}
+
#ifdef HAVE_EPOXY
if (screen_info->glx_context)
{
@@ -3799,6 +4025,7 @@ compositorUpdateScreenSize (ScreenInfo *screen_info)
{
#ifdef HAVE_COMPOSITOR
DisplayInfo *display_info;
+ gushort buffer;
g_return_if_fail (screen_info != NULL);
TRACE ("entering compositorUpdateScreenSize");
@@ -3815,10 +4042,24 @@ compositorUpdateScreenSize (ScreenInfo *screen_info)
XResizeWindow (display_info->dpy, screen_info->root_overlay, screen_info->width, screen_info->height);
}
#endif
- if (screen_info->rootBuffer)
+ if (screen_info->zoomBuffer)
{
- XRenderFreePicture (display_info->dpy, screen_info->rootBuffer);
- screen_info->rootBuffer = None;
+ XRenderFreePicture (display_info->dpy, screen_info->zoomBuffer);
+ screen_info->zoomBuffer = None;
+ }
+
+ for (buffer = 0; buffer < 2; buffer++)
+ {
+ if (screen_info->rootPixmap[buffer])
+ {
+ XFreePixmap (display_info->dpy, screen_info->rootPixmap[buffer]);
+ screen_info->rootPixmap[buffer] = None;
+ }
+ if (screen_info->rootBuffer[buffer])
+ {
+ XRenderFreePicture (display_info->dpy, screen_info->rootBuffer[buffer]);
+ screen_info->rootBuffer[buffer] = None;
+ }
}
damage_screen (screen_info);
#endif /* HAVE_COMPOSITOR */
diff --git a/src/display.h b/src/display.h
index 19412be..a2f8a9a 100644
--- a/src/display.h
+++ b/src/display.h
@@ -350,6 +350,13 @@ struct _DisplayInfo
gboolean have_overlays;
#endif /* HAVE_OVERLAYS */
+#ifdef HAVE_PRESENT_EXTENSION
+ gboolean have_present;
+ gint present_opcode;
+ gint present_error_base;
+ gint present_event_base;
+#endif /* HAVE_PRESENT_EXTENSION */
+
#endif /* HAVE_COMPOSITOR */
};
diff --git a/src/main.c b/src/main.c
index 5550b37..fbf5656 100644
--- a/src/main.c
+++ b/src/main.c
@@ -364,6 +364,12 @@ print_version (void)
g_print ("No\n");
#endif
+ g_print ("\t- Xpresent support: ");
+#ifdef HAVE_PRESENT_EXTENSION
+ g_print ("Yes\n");
+#else
+ g_print ("No\n");
+#endif
g_print ("\t- Embedded compositor: ");
#ifdef HAVE_COMPOSITOR
g_print ("Yes\n");
diff --git a/src/screen.h b/src/screen.h
index b87a103..c14bded 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -61,6 +61,7 @@
SuperMask | \
HyperMask)
+
#ifdef HAVE_COMPOSITOR
struct _gaussian_conv {
int size;
@@ -176,10 +177,14 @@ struct _ScreenInfo
guchar *shadowCorner;
guchar *shadowTop;
+ gushort current_buffer;
+ Pixmap rootPixmap[2];
+ Picture rootBuffer[2];
+ Picture zoomBuffer;
Picture rootPicture;
- Picture rootBuffer;
Picture blackPicture;
Picture rootTile;
+ XserverRegion prevDamage;
XserverRegion allDamage;
unsigned long cursorSerial;
Picture cursorPicture;
@@ -206,6 +211,10 @@ struct _ScreenInfo
GLXWindow glx_window;
#endif /* HAVE_EPOXY */
+#ifdef HAVE_PRESENT_EXTENSION
+ gboolean present_pending;
+#endif /* HAVE_PRESENT_EXTENSION */
+
#endif /* HAVE_COMPOSITOR */
};
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list