Compare commits

...

1 Commits

Author SHA1 Message Date
Jasper St. Pierre
d3b614836f gdkwindow-x11: Implement support for the X Present extension
This allows us better synchronization than simply using XCopyArea, which
is what cairo does by default.
2014-11-20 18:20:58 -08:00
7 changed files with 100 additions and 3 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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 */

View File

@@ -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))

View File

@@ -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.

View File

@@ -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;
}