unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* RFC: flicker-free double-buffered Emacs under X11
@ 2016-10-21  1:32 Daniel Colascione
  2016-10-21  2:27 ` Lars Ingebrigtsen
                   ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Daniel Colascione @ 2016-10-21  1:32 UTC (permalink / raw)
  To: emacs-devel

This patch teaches Emacs how to use the X11 DOUBLE-BUFFER extension to 
avoid showing the user incomplete drawing results. Without this patch, I 
can make Emacs flicker like crazy by running isearch for a piece of text 
unique in a buffer and holding down C-s. With this patch, Emacs does not 
flicker no matter what I do to it.

The patch also stops flickering that occurs when using the "solid 
resizing" feature of some window managers --- i.e., when the WM redraws 
windows as the user drags their edges, as opposed to displaying some 
kind of bounding-box in lieu of the actual window contents.

I've tried to avoid changing the logic in the single-buffered case 
(which we still support), and I've also tried to avoid touching Cairo 
rendering. This patch should work with any toolkit --- I've tested GTK+3 
and no toolkit at all.

A few notes:

* We do a buffer flip at the end of redisplay instead of in 
x_update_end() so the user never sees the completely-cleared state that 
we enter immediately after clear_garbaged_frames(). x_update_end() does 
do a buffer flip if it's called outside redisplay. I've added a new 
terminal hook to support this hack.

* The DBE documentation claims that XClearWindow and XClearArea clear 
both the front and back buffers. It's a lie. In my experiments, these 
functions clear only the front buffer.

* XFT stops drawing after we give XftCreateDraw a DBE back-buffer and 
the size of that back buffer changes. To work around this problem, we 
discard any caches XftDraw object we might have to a frame after that 
frame changes size. I haven't noticed any performance problems.

commit 15fdd8f63533201f05627ede634a8f5ae4757d7e
Author: Daniel Colascione <dancol@dancol.org>
Date:   Thu Oct 20 16:50:54 2016 -0700

     Add double-buffered output support to Emacs

diff --git a/configure.ac b/configure.ac
index cd11b10..4716b43 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3712,6 +3712,24 @@ AC_DEFUN
  AC_SUBST(XFIXES_CFLAGS)
  AC_SUBST(XFIXES_LIBS)

+### Use Xdbe (-lXdbe) if available
+HAVE_XDBE=no
+if test "${HAVE_X11}" = "yes"; then
+  AC_CHECK_HEADER(X11/extensions/Xdbe.h,
+    [AC_CHECK_LIB(Xext, XdbeAllocateBackBufferName, HAVE_XDBE=yes)],
+    [],
+    [#include <X11/Xlib.h>
+    ])
+  if test $HAVE_XDBE = yes; then
+    XDBE_LIBS=-lXext
+  fi
+  if test $HAVE_XDBE = yes; then
+    AC_DEFINE(HAVE_XDBE, 1, [Define to 1 if you have the Xdbe extension.])
+  fi
+fi
+AC_SUBST(XDBE_CFLAGS)
+AC_SUBST(XDBE_LIBS)
+
  ### Use libxml (-lxml2) if available
  ### mingw32 doesn't use -lxml2, since it loads the library dynamically.
  HAVE_LIBXML2=no
diff --git a/src/Makefile.in b/src/Makefile.in
index 89f7a92..dc0bfff 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -254,6 +254,9 @@ XINERAMA_CFLAGS =
  XFIXES_LIBS = @XFIXES_LIBS@
  XFIXES_CFLAGS = @XFIXES_CFLAGS@

+XDBE_LIBS = @XDBE_LIBS@
+XDBE_CFLAGS = @XDBE_CFLAGS@
+
  ## widget.o if USE_X_TOOLKIT, otherwise empty.
  WIDGET_OBJ=@WIDGET_OBJ@

@@ -372,7 +375,7 @@ ALL_CFLAGS=
    $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
    $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
    $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
-  $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
+  $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
    $(WEBKIT_CFLAGS) \
    $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
    $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
@@ -489,6 +492,7 @@ LIBES =
     $(WEBKIT_LIBS) \
     $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
     $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
+   $(XDBE_LIBS) \
     $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
     $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) 
$(LIBSELINUX_LIBS) \
     $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
diff --git a/src/dispnew.c b/src/dispnew.c
index 70d4de0..8f81cee 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -2999,6 +2999,7 @@ redraw_frame (struct frame *f)
  {
    /* Error if F has no glyphs.  */
    eassert (f->glyphs_initialized_p);
+  font_flush_frame_caches (f);
    update_begin (f);
    if (FRAME_MSDOS_P (f))
      FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f));
diff --git a/src/font.c b/src/font.c
index f8e6794..033995e 100644
--- a/src/font.c
+++ b/src/font.c
@@ -5275,6 +5275,16 @@ font_deferred_log (const char *action, 
Lisp_Object arg, Lisp_Object result)
  }

  void
+font_flush_frame_caches (struct frame *f)
+{
+  struct font_driver_list *list;
+
+  for (list = f->font_driver_list; list; list = list->next)
+    if (list->on && list->driver->flush_frame_caches)
+      list->driver->flush_frame_caches (f);
+}
+
+void
  syms_of_font (void)
  {
    sort_shift_bits[FONT_TYPE_INDEX] = 0;
diff --git a/src/font.h b/src/font.h
index cf47729..961e9c4 100644
--- a/src/font.h
+++ b/src/font.h
@@ -763,6 +763,12 @@ struct font_driver
       Return non-nil if the driver support rendering of combining
       characters for FONT according to Unicode combining class.  */
    Lisp_Object (*combining_capability) (struct font *font);
+
+  /* Optional
+
+     Called when frame F is redrawn from scratch.  Font engines may
+     invalidate certain caches in this case.  */
+  void (*flush_frame_caches) (struct frame *f);
  };


@@ -862,7 +868,9 @@ extern void *font_get_frame_data (struct frame *f, 
Lisp_Object);
  extern void font_filter_properties (Lisp_Object font,
  				    Lisp_Object alist,
  				    const char *const boolean_properties[],
-				    const char *const non_boolean_properties[]);
+                                    const char *const 
non_boolean_properties[]);
+
+extern void font_flush_frame_caches (struct frame *f);

  #ifdef HAVE_FREETYPE
  extern struct font_driver ftfont_driver;
diff --git a/src/ftxfont.c b/src/ftxfont.c
index f49d44f..bfdeb40 100644
--- a/src/ftxfont.c
+++ b/src/ftxfont.c
@@ -95,7 +95,7 @@ ftxfont_get_gcs (struct frame *f, unsigned long 
foreground, unsigned long backgr
        if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
  	break;
        xgcv.foreground = color.pixel;
-      new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+      new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), 
FRAME_X_DRAWABLE (f),
  				   GCForeground, &xgcv);
      }
    unblock_input ();
@@ -139,14 +139,14 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, 
GC *gcs, struct font *font,
  		p[n[0]].y = y - bitmap.top + i;
  		if (++n[0] == size)
  		  {
-		    XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                    XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  				 gc_fore, p, size, CoordModeOrigin);
  		    n[0] = 0;
  		  }
  	      }
  	}
        if (flush && n[0] > 0)
-	XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+        XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  		     gc_fore, p, n[0], CoordModeOrigin);
      }
    else
@@ -168,7 +168,7 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC 
*gcs, struct font *font,
  		  pp[n[idx]].y = y - bitmap.top + i;
  		  if (++(n[idx]) == size)
  		    {
-		      XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                      XDrawPoints (FRAME_X_DISPLAY (f), 
FRAME_X_DRAWABLE (f),
  				   idx == 6 ? gc_fore : gcs[idx], pp, size,
  				   CoordModeOrigin);
  		      n[idx] = 0;
@@ -180,10 +180,10 @@ ftxfont_draw_bitmap (struct frame *f, GC gc_fore, 
GC *gcs, struct font *font,
  	{
  	  for (i = 0; i < 6; i++)
  	    if (n[i] > 0)
-	      XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+              XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  			   gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
  	  if (n[6] > 0)
-	    XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+            XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  			 gc_fore, p + 0x600, n[6], CoordModeOrigin);
  	}
      }
@@ -203,7 +203,7 @@ ftxfont_draw_background (struct frame *f, struct 
font *font, GC gc, int x, int y
    XGetGCValues (FRAME_X_DISPLAY (f), gc,
  		GCForeground | GCBackground, &xgcv);
    XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
-  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
  		  x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
    XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
  }
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 88e6d30..f81940b 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -48,6 +48,10 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
  #include "emacsgtkfixed.h"
  #endif

+#ifdef HAVE_XDBE
+#include <X11/extensions/Xdbe.h>
+#endif
+
  #ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
  #define gtk_widget_set_has_window(w, b) \
    (gtk_fixed_set_has_window (GTK_FIXED (w), b))
@@ -1233,6 +1237,7 @@ xg_create_frame_widgets (struct frame *f)
       by callers of this function.  */
    gtk_widget_realize (wfixed);
    FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed);
+  set_up_x_back_buffer (f);

    /* Since GTK clears its window by filling with the background color,
       we must keep X and GTK background in sync.  */
@@ -1296,6 +1301,15 @@ xg_free_frame_widgets (struct frame *f)
        if (tbinfo)
          xfree (tbinfo);

+#ifdef HAVE_XDBE
+      if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
+        {
+          XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
+                                        FRAME_X_DRAWABLE (f));
+          FRAME_X_DRAWABLE (f) = 0;
+        }
+#endif
+
        gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
        FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
        FRAME_GTK_OUTER_WIDGET (f) = 0;
diff --git a/src/image.c b/src/image.c
index 9bd2455..1303a93 100644
--- a/src/image.c
+++ b/src/image.c
@@ -220,7 +220,7 @@ x_create_bitmap_from_data (struct frame *f, char 
*bits, unsigned int width, unsi

  #ifdef HAVE_X_WINDOWS
    Pixmap bitmap;
-  bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE 
(f),
  				  bits, width, height);
    if (! bitmap)
      return -1;
@@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, 
Lisp_Object file)

    filename = SSDATA (found);

-  result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  			    filename, &width, &height, &bitmap, &xhot, &yhot);
    if (result != BitmapSuccess)
      return -1;
@@ -1952,7 +1952,7 @@ x_create_x_image_and_pixmap (struct frame *f, int 
width, int height, int depth,
  {
  #ifdef HAVE_X_WINDOWS
    Display *display = FRAME_X_DISPLAY (f);
-  Window window = FRAME_X_WINDOW (f);
+  Drawable drawable = FRAME_X_DRAWABLE (f);
    Screen *screen = FRAME_X_SCREEN (f);

    eassert (input_blocked_p ());
@@ -1981,7 +1981,7 @@ x_create_x_image_and_pixmap (struct frame *f, int 
width, int height, int depth,
    (*ximg)->data = xmalloc ((*ximg)->bytes_per_line * height);

    /* Allocate a pixmap of the same size.  */
-  *pixmap = XCreatePixmap (display, window, width, height, depth);
+  *pixmap = XCreatePixmap (display, drawable, width, height, depth);
    if (*pixmap == NO_PIXMAP)
      {
        x_destroy_x_image (*ximg);
@@ -2742,7 +2742,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, 
struct image *img, char *data,
    img->pixmap =
     (x_check_image_size (0, img->width, img->height)
      ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
-				   FRAME_X_WINDOW (f),
+                                   FRAME_X_DRAWABLE (f),
  				   data,
  				   img->width, img->height,
  				   fg, bg,
@@ -3520,7 +3520,7 @@ x_create_bitmap_from_xpm_data (struct frame *f, 
const char **bits)
    xpm_init_color_cache (f, &attrs);
  #endif

-  rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  				(char **) bits, &bitmap, &mask, &attrs);
    if (rc != XpmSuccess)
      {
@@ -3758,7 +3758,7 @@ xpm_load (struct frame *f, struct image *img)
  #ifdef HAVE_X_WINDOWS
    if (rc == XpmSuccess)
      {
-      img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+      img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), 
FRAME_X_DRAWABLE (f),
  				   img->ximg->width, img->ximg->height,
  				   img->ximg->depth);
        if (img->pixmap == NO_PIXMAP)
@@ -3768,7 +3768,7 @@ xpm_load (struct frame *f, struct image *img)
  	}
        else if (img->mask_img)
  	{
-	  img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+          img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), 
FRAME_X_DRAWABLE (f),
  				     img->mask_img->width,
  				     img->mask_img->height,
  				     img->mask_img->depth);
@@ -9541,7 +9541,7 @@ gs_load (struct frame *f, struct image *img)
      {
        /* Only W32 version did BLOCK_INPUT here.  ++kfs */
        block_input ();
-      img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+      img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), 
FRAME_X_DRAWABLE (f),
  				   img->width, img->height,
  				   DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
        unblock_input ();
@@ -9557,7 +9557,7 @@ gs_load (struct frame *f, struct image *img)
       if successful.  We do not record_unwind_protect here because
       other places in redisplay like calling window scroll functions
       don't either.  Let the Lisp loader use `unwind-protect' instead.  */
-  printnum1 = FRAME_X_WINDOW (f);
+  printnum1 = FRAME_X_DRAWABLE (f);
    printnum2 = img->pixmap;
    window_and_pixmap_id
      = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
diff --git a/src/termhooks.h b/src/termhooks.h
index ff74d99..c8d7fae 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -477,6 +477,7 @@ struct terminal

    void (*update_begin_hook) (struct frame *);
    void (*update_end_hook) (struct frame *);
+  void (*redisplay_end_hook) (struct frame *);
    void (*set_terminal_window_hook) (struct frame *, int);

    /* Multi-frame and mouse support hooks.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index 3af5ea4..04f0ca1 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2501,7 +2501,7 @@ remember_mouse_glyph (struct frame *f, int gx, int 
gy, NativeRectangle *rect)

    /* Visible feedback for debugging.  */
  #if false && defined HAVE_X_WINDOWS
-  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  		  f->output_data.x->normal_gc,
  		  gx, gy, width, height);
  #endif
@@ -14211,6 +14211,13 @@ redisplay_internal (void)
        windows_or_buffers_changed = 0;
      }

+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_TERMINAL (f)->redisplay_end_hook)
+        (*FRAME_TERMINAL (f)->redisplay_end_hook) (f);
+    }
+
    /* Start SIGIO interrupts coming again.  Having them off during the
       code above makes it less likely one will discard output, but not
       impossible, since there might be stuff in the system buffer here.
@@ -24608,7 +24615,7 @@ init_glyph_string (struct glyph_string *s,
    s->hdc = hdc;
  #endif
    s->display = FRAME_X_DISPLAY (s->f);
-  s->window = FRAME_X_WINDOW (s->f);
+  s->window = FRAME_X_DRAWABLE (s->f);
    s->char2b = char2b;
    s->hl = hl;
    s->row = row;
diff --git a/src/xfaces.c b/src/xfaces.c
index 5837f35..accb98b 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -495,7 +495,7 @@ x_create_gc (struct frame *f, unsigned long mask, 
XGCValues *xgcv)
  {
    GC gc;
    block_input ();
-  gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, xgcv);
+  gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), mask, xgcv);
    unblock_input ();
    IF_DEBUG (++ngcs);
    return gc;
diff --git a/src/xfns.c b/src/xfns.c
index 8571d0e..2098036 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -53,6 +53,10 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
  #include "gtkutil.h"
  #endif

+#ifdef HAVE_XDBE
+#include <X11/extensions/Xdbe.h>
+#endif
+
  #ifdef USE_X_TOOLKIT
  #include <X11/Shell.h>

@@ -2483,6 +2487,29 @@ xic_set_xfontset (struct frame *f, const char 
*base_fontname)


  \f
+
+void
+set_up_x_back_buffer (struct frame* f)
+{
+  FRAME_X_DRAWABLE (f) = FRAME_X_WINDOW (f);
+#ifdef HAVE_XDBE
+  if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
+    {
+      /* If allocating a back buffer fails, just use single-buffered
+         rendering.  */
+      x_sync (f);
+      x_catch_errors (FRAME_X_DISPLAY (f));
+      FRAME_X_DRAWABLE (f) = XdbeAllocateBackBufferName (
+        FRAME_X_DISPLAY (f),
+        FRAME_X_WINDOW (f),
+        XdbeCopied);
+      if (x_had_errors_p (FRAME_X_DISPLAY (f)))
+        FRAME_X_DRAWABLE (f) = FRAME_X_WINDOW (f);
+      x_uncatch_errors_after_check ();
+    }
+#endif
+}
+
  #ifdef USE_X_TOOLKIT

  /* Create and set up the X widget for frame F.  */
@@ -2638,7 +2665,7 @@ x_window (struct frame *f, long window_prompting)
  		     f->output_data.x->parent_desc, 0, 0);

    FRAME_X_WINDOW (f) = XtWindow (frame_widget);
-
+  set_up_x_back_buffer (f);
    validate_x_resource_name ();

    class_hints.res_name = SSDATA (Vx_resource_name);
@@ -2784,7 +2811,8 @@ x_window (struct frame *f)
  		     CopyFromParent, /* depth */
  		     InputOutput, /* class */
  		     FRAME_X_VISUAL (f),
-		     attribute_mask, &attributes);
+                     attribute_mask, &attributes);
+  set_up_x_back_buffer (f);

  #ifdef HAVE_X_I18N
    if (use_xim)
@@ -2938,7 +2966,7 @@ x_make_gc (struct frame *f)
    gc_values.line_width = 0;	/* Means 1 using fast algorithm.  */
    f->output_data.x->normal_gc
      = XCreateGC (FRAME_X_DISPLAY (f),
-		 FRAME_X_WINDOW (f),
+                 FRAME_X_DRAWABLE (f),
  		 GCLineWidth | GCForeground | GCBackground,
  		 &gc_values);

@@ -2947,7 +2975,7 @@ x_make_gc (struct frame *f)
    gc_values.background = FRAME_FOREGROUND_PIXEL (f);
    f->output_data.x->reverse_gc
      = XCreateGC (FRAME_X_DISPLAY (f),
-		 FRAME_X_WINDOW (f),
+                 FRAME_X_DRAWABLE (f),
  		 GCForeground | GCBackground | GCLineWidth,
  		 &gc_values);

@@ -2956,7 +2984,7 @@ x_make_gc (struct frame *f)
    gc_values.background = f->output_data.x->cursor_pixel;
    gc_values.fill_style = FillOpaqueStippled;
    f->output_data.x->cursor_gc
-    = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+    = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  		 (GCForeground | GCBackground
  		  | GCFillStyle | GCLineWidth),
  		 &gc_values);
@@ -5636,7 +5664,8 @@ x_create_tip_frame (struct x_display_info 
*dpyinfo, Lisp_Object parms)
  		       /* Border.  */
  		       f->border_width,
  		       CopyFromParent, InputOutput, CopyFromParent,
-		       mask, &attrs);
+                       mask, &attrs);
+    set_up_x_back_buffer (f);
      XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
                       FRAME_DISPLAY_INFO (f)->Xatom_net_window_type,
                       XA_ATOM, 32, PropModeReplace,
diff --git a/src/xfont.c b/src/xfont.c
index 45b0e0a..c2b7317 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -1057,20 +1057,20 @@ xfont_draw (struct glyph_string *s, int from, 
int to, int x, int y,
  	{
  	  if (s->padding_p)
  	    for (i = 0; i < len; i++)
-	      XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+              XDrawImageString (FRAME_X_DISPLAY (s->f), 
FRAME_X_DRAWABLE (s->f),
  				gc, x + i, y, str + i, 1);
  	  else
-	    XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+            XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE 
(s->f),
  			      gc, x, y, str, len);
  	}
        else
  	{
  	  if (s->padding_p)
  	    for (i = 0; i < len; i++)
-	      XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+              XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
  			   gc, x + i, y, str + i, 1);
  	  else
-	    XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+            XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
  			 gc, x, y, str, len);
  	}
        unblock_input ();
@@ -1083,20 +1083,20 @@ xfont_draw (struct glyph_string *s, int from, 
int to, int x, int y,
      {
        if (s->padding_p)
  	for (i = 0; i < len; i++)
-	  XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+          XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE 
(s->f),
  			      gc, x + i, y, s->char2b + from + i, 1);
        else
-	XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+        XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE 
(s->f),
  			    gc, x, y, s->char2b + from, len);
      }
    else
      {
        if (s->padding_p)
  	for (i = 0; i < len; i++)
-	  XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+          XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
  			 gc, x + i, y, s->char2b + from + i, 1);
        else
-	XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
+        XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
  		       gc, x, y, s->char2b + from, len);
      }
    unblock_input ();
diff --git a/src/xftfont.c b/src/xftfont.c
index 34c6f7d..447adf6 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -586,7 +586,7 @@ xftfont_get_xft_draw (struct frame *f)
      {
        block_input ();
        xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
-			       FRAME_X_WINDOW (f),
+                               FRAME_X_DRAWABLE (f),
  			       FRAME_X_VISUAL (f),
  			       FRAME_X_COLORMAP (f));
        unblock_input ();
@@ -695,6 +695,13 @@ xftfont_end_for_frame (struct frame *f)
    return 0;
  }

+static void
+xftfont_flush_frame_caches (struct frame *f)
+{
+  if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
+    xftfont_end_for_frame (f);
+}
+
  static bool
  xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
                          Lisp_Object entity)
@@ -777,6 +784,9 @@ This is needed with some fonts to correct vertical 
overlap of glyphs.  */);
  #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
    xftfont_driver.shape = xftfont_shape;
  #endif
+  // When using X double buffering, the XftDraw structure we
+  // build seems to be useless once a frame is resized, so
+  xftfont_driver.flush_frame_caches = xftfont_flush_frame_caches;

    register_font_driver (&xftfont_driver, NULL);
  }
diff --git a/src/xterm.c b/src/xterm.c
index 7476694..7116784 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -45,6 +45,10 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
  #include <X11/extensions/Xrender.h>
  #endif

+#ifdef HAVE_XDBE
+#include <X11/extensions/Xdbe.h>
+#endif
+
  /* Load sys/types.h if not already loaded.
     In some systems loading it twice is suicidal.  */
  #ifndef makedev
@@ -360,7 +364,7 @@ x_begin_cr_clip (struct frame *f, GC gc)
          {
            cairo_surface_t *surface;
            surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
-                                               FRAME_X_WINDOW (f),
+                                               FRAME_X_DRAWABLE (f),
                                                 FRAME_DISPLAY_INFO 
(f)->visual,
                                                 FRAME_PIXEL_WIDTH (f),
                                                 FRAME_PIXEL_HEIGHT (f));
@@ -722,7 +726,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int 
y, int width, int height)
    cairo_fill (cr);
    x_end_cr_clip (f);
  #else
-  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  		  gc, x, y, width, height);
  #endif
  }
@@ -740,7 +744,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int 
y, int width, int height)
    cairo_stroke (cr);
    x_end_cr_clip (f);
  #else
-  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  		  gc, x, y, width, height);
  #endif
  }
@@ -756,7 +760,10 @@ x_clear_window (struct frame *f)
    cairo_paint (cr);
    x_end_cr_clip (f);
  #else
-  XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+  if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
+    x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
+  else
+    XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
  #endif
  }

@@ -1067,7 +1074,7 @@ x_draw_vertical_window_border (struct window *w, 
int x, int y0, int y1)
  #ifdef USE_CAIRO
    x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
  #else
-  XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
  	     f->output_data.x->normal_gc, x, y0, x, y1);
  #endif
  }
@@ -1179,6 +1186,21 @@ x_update_window_end (struct window *w, bool 
cursor_on_p,
  /* End update of frame F.  This function is installed as a hook in
     update_end.  */

+#if defined (HAVE_XDBE)
+static void
+show_back_buffer (struct frame *f)
+{
+  if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
+    {
+      XdbeSwapInfo swap_info;
+      memset (&swap_info, 0, sizeof (swap_info));
+      swap_info.swap_window = FRAME_X_WINDOW (f);
+      swap_info.swap_action = XdbeCopied;
+      XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
+    }
+}
+#endif
+
  static void
  x_update_end (struct frame *f)
  {
@@ -1207,7 +1229,7 @@ x_update_end (struct frame *f)
            if (! FRAME_EXTERNAL_MENU_BAR (f))
              height += FRAME_MENU_BAR_HEIGHT (f);
            surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
-                                               FRAME_X_WINDOW (f),
+                                               FRAME_X_DRAWABLE (f),
                                                 FRAME_DISPLAY_INFO 
(f)->visual,
                                                 width,
                                                 height);
@@ -1220,7 +1242,14 @@ x_update_end (struct frame *f)
        cairo_destroy (cr);
        unblock_input ();
      }
-#endif /* USE_CAIRO */
+#endif
+
+#ifdef HAVE_XDBE
+  if (redisplaying_p)
+    FRAME_X_NEED_BUFFER_FLIP (f) = true;
+  else
+    show_back_buffer (f);
+#endif

  #ifndef XFlush
    block_input ();
@@ -1229,6 +1258,17 @@ x_update_end (struct frame *f)
  #endif
  }

+static void
+x_redisplay_end (struct frame *f)
+{
+#ifdef HAVE_XDBE
+  if (FRAME_X_NEED_BUFFER_FLIP (f))
+    {
+      show_back_buffer (f);
+      FRAME_X_NEED_BUFFER_FLIP (f) = false;
+    }
+#endif
+}

  /* This function is called from various places in xdisp.c
     whenever a complete update has been performed.  */
@@ -1354,7 +1394,7 @@ x_draw_fringe_bitmap (struct window *w, struct 
glyph_row *row, struct draw_fring
  #else  /* not USE_CAIRO */
    if (p->which)
      {
-      Window window = FRAME_X_WINDOW (f);
+      Drawable drawable = FRAME_X_DRAWABLE (f);
        char *bits;
        Pixmap pixmap, clipmask = (Pixmap) 0;
        int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
@@ -1367,7 +1407,7 @@ x_draw_fringe_bitmap (struct window *w, struct 
glyph_row *row, struct draw_fring

        /* Draw the bitmap.  I believe these small pixmaps can be cached
  	 by the server.  */
-      pixmap = XCreatePixmapFromBitmapData (display, window, bits, 
p->wd, p->h,
+      pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, 
p->wd, p->h,
  					    (p->cursor_p
  					     ? (p->overlay_p ? face->background
  						: f->output_data.x->cursor_pixel)
@@ -1386,7 +1426,7 @@ x_draw_fringe_bitmap (struct window *w, struct 
glyph_row *row, struct draw_fring
  	  XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, 
&gcv);
  	}

-      XCopyArea (display, pixmap, window, gc, 0, 0,
+      XCopyArea (display, pixmap, drawable, gc, 0, 0,
  		 p->wd, p->h, p->x, p->y);
        XFreePixmap (display, pixmap);

@@ -2565,7 +2605,7 @@ x_setup_relief_color (struct frame *f, struct 
relief *relief, double factor,
      {
        xgcv.stipple = dpyinfo->gray;
        mask |= GCStipple;
-      relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
+      relief->gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f), mask, &xgcv);
      }
    else
      XChangeGC (dpy, relief->gc, mask, &xgcv);
@@ -2696,7 +2736,7 @@ x_draw_relief_rect (struct frame *f,
    x_reset_clip_rectangles (f, bottom_right_gc);
  #else
    Display *dpy = FRAME_X_DISPLAY (f);
-  Window window = FRAME_X_WINDOW (f);
+  Drawable drawable = FRAME_X_DRAWABLE (f);
    int i;
    GC gc;

@@ -2715,12 +2755,12 @@ x_draw_relief_rect (struct frame *f,
    if (top_p)
      {
        if (width == 1)
-	XDrawLine (dpy, window, gc,
+        XDrawLine (dpy, drawable, gc,
  		   left_x + left_p, top_y,
  		   right_x + !right_p, top_y);

        for (i = 1; i < width; ++i)
-	XDrawLine (dpy, window, gc,
+        XDrawLine (dpy, drawable, gc,
  		   left_x  + i * left_p, top_y + i,
  		   right_x + 1 - i * right_p, top_y + i);
      }
@@ -2729,13 +2769,13 @@ x_draw_relief_rect (struct frame *f,
    if (left_p)
      {
        if (width == 1)
-	XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
+        XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);

-      XClearArea (dpy, window, left_x, top_y, 1, 1, False);
-      XClearArea (dpy, window, left_x, bottom_y, 1, 1, False);
+      x_clear_area(f, left_x, top_y, 1, 1);
+      x_clear_area(f, left_x, bottom_y, 1, 1);

        for (i = (width > 1 ? 1 : 0); i < width; ++i)
-	XDrawLine (dpy, window, gc,
+        XDrawLine (dpy, drawable, gc,
  		   left_x + i, top_y + (i + 1) * top_p,
  		   left_x + i, bottom_y + 1 - (i + 1) * bot_p);
      }
@@ -2751,23 +2791,23 @@ x_draw_relief_rect (struct frame *f,
      {
        /* Outermost top line.  */
        if (top_p)
-	XDrawLine (dpy, window, gc,
+        XDrawLine (dpy, drawable, gc,
  		   left_x  + left_p, top_y,
  		   right_x + !right_p, top_y);

        /* Outermost left line.  */
        if (left_p)
-	XDrawLine (dpy, window, gc, left_x, top_y + 1, left_x, bottom_y);
+        XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
      }

    /* Bottom.  */
    if (bot_p)
      {
-      XDrawLine (dpy, window, gc,
+      XDrawLine (dpy, drawable, gc,
  		 left_x + left_p, bottom_y,
  		 right_x + !right_p, bottom_y);
        for (i = 1; i < width; ++i)
-	XDrawLine (dpy, window, gc,
+        XDrawLine (dpy, drawable, gc,
  		   left_x  + i * left_p, bottom_y - i,
  		   right_x + 1 - i * right_p, bottom_y - i);
      }
@@ -2775,10 +2815,10 @@ x_draw_relief_rect (struct frame *f,
    /* Right.  */
    if (right_p)
      {
-      XClearArea (dpy, window, right_x, top_y, 1, 1, False);
-      XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
+      x_clear_area(f, right_x, top_y, 1, 1);
+      x_clear_area(f, right_x, bottom_y, 1, 1);
        for (i = 0; i < width; ++i)
-	XDrawLine (dpy, window, gc,
+        XDrawLine (dpy, drawable, gc,
  		   right_x - i, top_y + (i + 1) * top_p,
  		   right_x - i, bottom_y + 1 - (i + 1) * bot_p);
      }
@@ -3741,7 +3781,7 @@ x_shift_glyphs_for_insert (struct frame *f, int x, 
int y, int width, int height,
  /* Never called on a GUI frame, see
     http://lists.gnu.org/archive/html/emacs-devel/2015-05/msg00456.html
  */
-  XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
+  XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), 
FRAME_X_DRAWABLE (f),
  	     f->output_data.x->normal_gc,
  	     x, y, width, height,
  	     x + shift_by, y);
@@ -3782,8 +3822,14 @@ x_clear_area (struct frame *f, int x, int y, int 
width, int height)
    cairo_fill (cr);
    x_end_cr_clip (f);
  #else
-  x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-		 x, y, width, height, False);
+    if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
+      XFillRectangle (FRAME_X_DISPLAY (f),
+                      FRAME_X_DRAWABLE (f),
+                      f->output_data.x->reverse_gc,
+                      x, y, width, height);
+  else
+    x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   x, y, width, height, False);
  #endif
  }

@@ -4109,7 +4155,7 @@ x_scroll_run (struct window *w, struct run *run)
    SET_FRAME_GARBAGED (f);
  #else
    XCopyArea (FRAME_X_DISPLAY (f),
-	     FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
+             FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
  	     f->output_data.x->normal_gc,
  	     x, from_y,
  	     width, height,
@@ -7769,6 +7815,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                SET_FRAME_VISIBLE (f, 1);
                SET_FRAME_ICONIFIED (f, false);
                f->output_data.x->has_been_visible = true;
+              font_flush_frame_caches (f);
                SET_FRAME_GARBAGED (f);
              }
            else
@@ -8437,7 +8484,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              {
                if (FRAME_PIXEL_HEIGHT (f) != 
configureEvent.xconfigure.height
                    || FRAME_PIXEL_WIDTH (f) != 
configureEvent.xconfigure.width)
-                SET_FRAME_GARBAGED (f);
+                {
+                  font_flush_frame_caches (f);
+                  SET_FRAME_GARBAGED (f);
+                }
                FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
                FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
              }
@@ -8463,7 +8513,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                || configureEvent.xconfigure.height != 
FRAME_PIXEL_HEIGHT (f))
              {
                change_frame_size (f, width, height, false, true, false, 
true);
-	      x_clear_under_internal_border (f);
+              x_clear_under_internal_border (f);
+              font_flush_frame_caches (f);
  	      SET_FRAME_GARBAGED (f);
                cancel_mouse_face (f);
              }
@@ -8880,7 +8931,7 @@ x_draw_hollow_cursor (struct window *w, struct 
glyph_row *row)
    if (dpyinfo->scratch_cursor_gc)
      XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
    else
-    dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
+    dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_DRAWABLE (f),
  					    GCForeground, &xgcv);
    gc = dpyinfo->scratch_cursor_gc;

@@ -8937,7 +8988,7 @@ x_draw_bar_cursor (struct window *w, struct 
glyph_row *row, int width, enum text
    else
      {
        Display *dpy = FRAME_X_DISPLAY (f);
-      Window window = FRAME_X_WINDOW (f);
+      Drawable drawable = FRAME_X_DRAWABLE (f);
        GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
        unsigned long mask = GCForeground | GCBackground | 
GCGraphicsExposures;
        struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
@@ -8958,7 +9009,7 @@ x_draw_bar_cursor (struct window *w, struct 
glyph_row *row, int width, enum text
  	XChangeGC (dpy, gc, mask, &xgcv);
        else
  	{
-	  gc = XCreateGC (dpy, window, mask, &xgcv);
+          gc = XCreateGC (dpy, drawable, mask, &xgcv);
  	  FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
  	}

@@ -11271,7 +11322,14 @@ x_free_frame_resources (struct frame *f)
  #endif /* USE_GTK */

        if (FRAME_X_WINDOW (f))
-	XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+        {
+#ifdef HAVE_XDBE
+          if (FRAME_X_WINDOW (f) != FRAME_X_DRAWABLE (f))
+            XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
+                                          FRAME_X_DRAWABLE (f));
+#endif
+          XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+        }
  #endif /* !USE_X_TOOLKIT */

        unload_color (f, FRAME_FOREGROUND_PIXEL (f));
@@ -12111,7 +12169,17 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
      }
    else
      dpyinfo->cmap = XCreateColormap (dpyinfo->display, 
dpyinfo->root_window,
-				     dpyinfo->visual, AllocNone);
+                                     dpyinfo->visual, AllocNone);
+
+#ifdef HAVE_XDBE
+  dpyinfo->supports_xdbe = false;
+    {
+      int xdbe_major;
+      int xdbe_minor;
+      if (XdbeQueryExtension (dpyinfo->display, &xdbe_major, &xdbe_minor))
+        dpyinfo->supports_xdbe = true;
+    }
+#endif

  #ifdef HAVE_XFT
    {
@@ -12590,6 +12658,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
    terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
    terminal->update_begin_hook = x_update_begin;
    terminal->update_end_hook = x_update_end;
+  terminal->redisplay_end_hook = x_redisplay_end;
    terminal->read_socket_hook = XTread_socket;
    terminal->frame_up_to_date_hook = XTframe_up_to_date;
    terminal->mouse_position_hook = XTmouse_position;
diff --git a/src/xterm.h b/src/xterm.h
index 675a484..cb1aa1d 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -475,6 +475,10 @@ struct x_display_info
  #ifdef USE_XCB
    xcb_connection_t *xcb_connection;
  #endif
+
+#ifdef HAVE_XDBE
+  bool supports_xdbe;
+#endif
  };

  #ifdef HAVE_X_I18N
@@ -527,6 +531,17 @@ struct x_output
       and the X window has not yet been created.  */
    Window window_desc;

+#ifdef HAVE_XDBE
+  /* The drawable to which we're rendering.  In the single-buffered
+     base, the window itself.  In the double-buffered case, the
+     window's back buffer.  */
+  Drawable draw_desc;
+
+  /* Set to true when we need a buffer flip.  We do a buffer flip only
+     at the end of redisplay in order to minimize flicker.  */
+  bool need_buffer_flip;
+#endif
+
    /* The X window used for the bitmap icon;
       or 0 if we don't have a bitmap icon.  */
    Window icon_desc;
@@ -737,6 +752,18 @@ enum
  /* Return the X window used for displaying data in frame F.  */
  #define FRAME_X_WINDOW(f) ((f)->output_data.x->window_desc)

+/* Return the drawable used for rendering to frame F.  */
+#ifdef HAVE_XDBE
+#define FRAME_X_DRAWABLE(f) ((f)->output_data.x->draw_desc)
+#else
+#define FRAME_X_DRAWABLE(f) (0,(FRAME_X_WINDOW (f)))
+#endif
+
+/* Return the need-buffer-flip flag for frame F.  */
+#ifdef HAVE_XDBE
+#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
+#endif
+
  /* Return the outermost X window associated with the frame F.  */
  #ifdef USE_X_TOOLKIT
  #define FRAME_OUTER_WINDOW(f) ((f)->output_data.x->widget ?             \
@@ -1140,6 +1167,8 @@ extern bool x_wm_supports (struct frame *, Atom);
  extern void x_wait_for_event (struct frame *, int);
  extern void x_clear_under_internal_border (struct frame *f);

+extern void set_up_x_back_buffer (struct frame* f);
+
  /* Defined in xselect.c.  */

  extern void x_handle_property_notify (const XPropertyEvent *);




^ permalink raw reply related	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2016-11-06 15:46 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-21  1:32 RFC: flicker-free double-buffered Emacs under X11 Daniel Colascione
2016-10-21  2:27 ` Lars Ingebrigtsen
2016-10-21  2:31   ` Daniel Colascione
2016-10-21  3:24 ` Óscar Fuentes
2016-10-21  3:31   ` Clément Pit--Claudel
2016-10-21  3:41     ` Óscar Fuentes
2016-10-21  3:50       ` Clément Pit--Claudel
2016-10-21  8:23     ` Andreas Schwab
2016-10-21  8:25       ` Andreas Schwab
2016-10-21  3:56 ` Clément Pit--Claudel
2016-10-21  8:49 ` Eli Zaretskii
2016-10-21 11:04   ` Daniel Colascione
2016-10-21 17:43     ` Eli Zaretskii
2016-10-21 18:27       ` Daniel Colascione
2016-10-21 19:27         ` Eli Zaretskii
2016-10-23 20:51           ` Daniel Colascione
2016-10-24  8:05             ` Eli Zaretskii
2016-10-24 18:43               ` Ken Raeburn
2016-10-27 19:06               ` dancol
2016-10-27 19:36                 ` Eli Zaretskii
     [not found]                   ` <db81befd-7a72-58d9-b7a8-107df89bcab3@dancol.org>
2016-10-27 19:56                     ` Daniel Colascione
2016-10-28  6:31                       ` Eli Zaretskii
2016-10-27 22:18                 ` Paul Eggert
2016-10-27 22:46                   ` Clément Pit--Claudel
2016-10-28 13:14                     ` Stefan Monnier
2016-11-01  0:03                       ` Dmitry Gutov
2016-10-27 23:10                   ` Daniel Colascione
2016-10-28  2:07                     ` Paul Eggert
2016-10-28  7:19                       ` Eli Zaretskii
2016-11-06  3:51                         ` Paul Eggert
2016-11-06 15:46                           ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).