diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2014-11-20 17:29:54 -0800 |
---|---|---|
committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2014-11-20 18:20:58 -0800 |
commit | d3b614836f5ea2960e068dbf62472bfb390239be (patch) | |
tree | 5c94a63d9b1f6e21422e1915bf59b74e03c6ea3a | |
parent | 5a0d1a79c5f9a709c22d740afd9334085529546a (diff) | |
download | gtk+-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.ac | 16 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 3 | ||||
-rw-r--r-- | gdk/gdkwindowimpl.c | 7 | ||||
-rw-r--r-- | gdk/gdkwindowimpl.h | 1 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 16 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.h | 2 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 58 |
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; } |