summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2014-11-20 17:29:54 -0800
committerJasper St. Pierre <jstpierre@mecheye.net>2014-11-20 18:20:58 -0800
commitd3b614836f5ea2960e068dbf62472bfb390239be (patch)
tree5c94a63d9b1f6e21422e1915bf59b74e03c6ea3a
parent5a0d1a79c5f9a709c22d740afd9334085529546a (diff)
downloadgtk+-d3b614836f5ea2960e068dbf62472bfb390239be.tar.gz
gdkwindow-x11: Implement support for the X Present extensionxpresent
This allows us better synchronization than simply using XCopyArea, which is what cairo does by default.
-rw-r--r--configure.ac16
-rw-r--r--gdk/gdkwindow.c3
-rw-r--r--gdk/gdkwindowimpl.c7
-rw-r--r--gdk/gdkwindowimpl.h1
-rw-r--r--gdk/x11/gdkdisplay-x11.c16
-rw-r--r--gdk/x11/gdkdisplay-x11.h2
-rw-r--r--gdk/x11/gdkwindow-x11.c58
7 files changed, 100 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 666bae1246..e0be9011f5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -310,6 +310,10 @@ AC_ARG_ENABLE(xdamage,
[AS_HELP_STRING([--enable-xdamage],
[support X Damage extension [default=maybe]])],,
[enable_xdamage="maybe"])
+AC_ARG_ENABLE(xpresent,
+ [AS_HELP_STRING([--enable-xpresent],
+ [support X Present extension [default=maybe]])],,
+ [enable_xpresent="maybe"])
AC_ARG_ENABLE(x11-backend,
[AS_HELP_STRING([--enable-x11-backend],
@@ -1286,6 +1290,18 @@ if test "x$enable_x11_backend" = xyes; then
fi
fi
+ if test x"$enable_xpresent" != xno; then
+ if $PKG_CONFIG --exists xcb-present ; then
+ AC_DEFINE(HAVE_PRESENT, 1, [Have the Present X extension])
+
+ X_PACKAGES="$X_PACKAGES xcb-present"
+ X_EXTENSIONS="$X_EXTENSIONS Present"
+ GTK_PACKAGES_FOR_X="$GTK_PACKAGES_FOR_X xcb-present"
+ elif test x"$enable_xpresent" = xyes; then
+ AC_MSG_ERROR([Present support requested but xcb-present not found])
+ fi
+ fi
+
if $have_base_x_pc ; then
GDK_EXTRA_LIBS="$x_extra_libs"
else
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 6d56a6c7e4..2c6517e196 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -3069,7 +3069,6 @@ gdk_window_end_paint (GdkWindow *window)
if (impl_class->end_paint)
impl_class->end_paint (window);
-
if (window->current_paint.surface_needs_composite)
{
cairo_surface_t *surface;
@@ -3101,7 +3100,7 @@ gdk_window_end_paint (GdkWindow *window)
window->current_paint.region,
window->active_update_area);
}
- else
+ else if (!impl_class->do_composite (window))
{
surface = gdk_window_ref_impl_surface (window);
cr = cairo_create (surface);
diff --git a/gdk/gdkwindowimpl.c b/gdk/gdkwindowimpl.c
index b7ec4eda24..3660fab58c 100644
--- a/gdk/gdkwindowimpl.c
+++ b/gdk/gdkwindowimpl.c
@@ -46,11 +46,18 @@ gdk_window_impl_process_updates_recurse (GdkWindow *window,
_gdk_window_process_updates_recurse (window, region);
}
+static gboolean
+gdk_window_impl_do_composite (GdkWindow *window)
+{
+ return FALSE;
+}
+
static void
gdk_window_impl_class_init (GdkWindowImplClass *impl_class)
{
impl_class->beep = gdk_window_impl_beep;
impl_class->process_updates_recurse = gdk_window_impl_process_updates_recurse;
+ impl_class->do_composite = gdk_window_impl_do_composite;
}
static void
diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h
index b8fb0f0286..b442325c85 100644
--- a/gdk/gdkwindowimpl.h
+++ b/gdk/gdkwindowimpl.h
@@ -299,6 +299,7 @@ struct _GdkWindowImplClass
GError **error);
void (*invalidate_for_new_frame)(GdkWindow *window,
cairo_region_t *update_area);
+ gboolean (*do_composite) (GdkWindow *window);
};
/* Interface Functions */
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index d6543c1e38..44e9c710a2 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -49,6 +49,7 @@
#include <X11/Xatom.h>
#include <X11/Xlibint.h>
+#include <X11/Xlib-xcb.h>
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
@@ -72,6 +73,10 @@
#include <X11/extensions/Xrandr.h>
#endif
+#ifdef HAVE_PRESENT
+#include <xcb/present.h>
+#endif
+
typedef struct _GdkErrorTrap GdkErrorTrap;
struct _GdkErrorTrap
@@ -1366,6 +1371,7 @@ _gdk_x11_display_open (const gchar *display_name)
GdkWindowAttr attr;
gint argc;
gchar *argv[1];
+ xcb_connection_t *xcb_conn;
XClassHint *class_hint;
gulong pid;
@@ -1386,6 +1392,8 @@ _gdk_x11_display_open (const gchar *display_name)
_gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
+ xcb_conn = XGetXCBConnection (display_x11->xdisplay);
+
/* RandR must be initialized before we initialize the screens */
display_x11->have_randr12 = FALSE;
display_x11->have_randr13 = FALSE;
@@ -1450,6 +1458,14 @@ _gdk_x11_display_open (const gchar *display_name)
#endif
display_x11->have_xfixes = FALSE;
+#ifdef HAVE_PRESENT
+ if (xcb_get_extension_data (xcb_conn, &xcb_present_id))
+ {
+ (void) xcb_present_query_version (xcb_conn, XCB_PRESENT_MAJOR_VERSION, XCB_PRESENT_MINOR_VERSION);
+ display_x11->have_present = TRUE;
+ }
+#endif
+
#ifdef HAVE_XCOMPOSITE
if (XCompositeQueryExtension (display_x11->xdisplay,
&ignore, &ignore))
diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h
index f601ed3763..a7fd8f2845 100644
--- a/gdk/x11/gdkdisplay-x11.h
+++ b/gdk/x11/gdkdisplay-x11.h
@@ -68,6 +68,8 @@ struct _GdkX11Display
gboolean have_randr13;
gint xrandr_event_base;
+ gboolean have_present;
+
/* If the SECURITY extension is in place, whether this client holds
* a trusted authorization and so is allowed to make various requests
* (grabs, properties etc.) Otherwise always TRUE.
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index a7be5de4bb..369a96a122 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -53,6 +53,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
+#include <X11/Xlib-xcb.h>
#include <X11/extensions/shape.h>
@@ -72,6 +73,10 @@
#include <X11/extensions/Xdamage.h>
#endif
+#ifdef HAVE_PRESENT
+#include <xcb/present.h>
+#endif
+
const int _gdk_x11_event_mask_table[21] =
{
ExposureMask,
@@ -3398,7 +3403,7 @@ do_shape_combine_region (GdkWindow *window,
_gdk_x11_region_get_xrectangles (shape_region,
0, 0, impl->window_scale,
&xrects, &n_rects);
-
+
if (shape == ShapeBounding)
{
_gdk_x11_window_tmp_unset_parent_bg (window);
@@ -5683,6 +5688,56 @@ gdk_x11_window_show_window_menu (GdkWindow *window,
return TRUE;
}
+static gboolean
+gdk_x11_window_do_composite (GdkWindow *window)
+{
+ GdkDisplay *display = gdk_window_get_display (window);
+ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+
+#ifdef HAVE_PRESENT
+ if (display_x11->have_present)
+ {
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ xcb_connection_t *xcb_conn = XGetXCBConnection (xdisplay);
+ XserverRegion update_region;
+ XRectangle *rects;
+ int n_rects;
+ double sx, sy;
+ double offs_x, offs_y;
+
+ cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
+ cairo_surface_get_device_offset (window->current_paint.surface, &offs_x, &offs_y);
+
+ _gdk_x11_region_get_xrectangles (window->current_paint.region,
+ offs_x / sx, offs_y / sy, sx, &rects, &n_rects);
+ update_region = XFixesCreateRegion (xdisplay, rects, n_rects);
+
+ xcb_present_pixmap (xcb_conn,
+ GDK_WINDOW_XID (window),
+ cairo_xlib_surface_get_drawable (window->current_paint.surface),
+ XNextRequest (xdisplay),
+ update_region,
+ update_region,
+ -offs_x,
+ -offs_y,
+ None, /* target_crtc */
+ None, /* wait_fence */
+ None, /* idle_fence */
+ 0, /* options */
+ 0, /* target_msc */
+ 0, /* divisor */
+ 0, /* remainder */
+ 0, NULL /* notifies */ );
+
+ XFixesDestroyRegion (xdisplay, update_region);
+
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
{
@@ -5773,4 +5828,5 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
impl_class->create_gl_context = gdk_x11_window_create_gl_context;
impl_class->invalidate_for_new_frame = gdk_x11_window_invalidate_for_new_frame;
impl_class->get_unscaled_size = gdk_x11_window_get_unscaled_size;
+ impl_class->do_composite = gdk_x11_window_do_composite;
}