]> git.eshelyaron.com Git - emacs.git/commitdiff
Clean up X11 double buffering code
authorPo Lu <luangruo@yahoo.com>
Tue, 3 May 2022 01:22:06 +0000 (09:22 +0800)
committerPo Lu <luangruo@yahoo.com>
Tue, 3 May 2022 01:22:06 +0000 (09:22 +0800)
This fixes several latent bugs where code went down the path
with double buffering enabled when it wasn't, and vice versa.

* src/xfns.c (x_set_inhibit_double_buffering): Improve
commentary and only define when HAVE_XDBE.
(x_mark_frame_dirty): Only set buffer flip flag when HAVE_XDBE.
(initial_set_up_x_back_buffer): Clean up coding style and remove
unnecessary block_input pair.
(Fx_double_buffered_p): Always return nil if !HAVE_XDBE.
(x_frame_parm_handlers): Don't set double buffering handler if
!HAVE_XDBE.

* src/xftfont.c (xftfont_drop_xrender_surfaces, xftfont_driver):
Only define when XDBE is available.

* src/xterm.c (x_drop_xrender_surfaces): Likewise.
(x_clear_window): Don't test double buffering flags when
!HAVE_XDBE.
(show_back_buffer): Only define when HAVE_XDBE.
(x_flip_and_flush): Don't try to flip when !HAVE_XDBE.
(XTframe_up_to_date): Likewise.
(XTbuffer_flipping_unblocked_hook): Only define when Xdbe is
available.
(x_clear_area): Don't test double buffering flags when Xdbe is
not available.
(flush_dirty_back_buffer_on): Don't define if there's no DBE.
(handle_one_xevent, x_create_terminal): Likewise.

* src/xterm.h (FRAME_X_DRAWABLE): Fix coding style.

src/xfns.c
src/xftfont.c
src/xterm.c
src/xterm.h

index 7176d626094734950a34902cad71f91e3f633681..14721c6ce83971cc7956012278a97c19df31f1f9 100644 (file)
@@ -823,22 +823,24 @@ x_set_tool_bar_position (struct frame *f,
     wrong_choice (choice, new_value);
 }
 
+#ifdef HAVE_XDBE
 static void
 x_set_inhibit_double_buffering (struct frame *f,
                                 Lisp_Object new_value,
                                 Lisp_Object old_value)
 {
-  block_input ();
+  bool want_double_buffering, was_double_buffered;
+
   if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
     {
-      bool want_double_buffering = NILP (new_value);
-      bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
-      /* font_drop_xrender_surfaces in xftfont does something only if
-         we're double-buffered, so call font_drop_xrender_surfaces before
-         and after any potential change.  One of the calls will end up
-         being a no-op.  */
+      want_double_buffering = NILP (new_value);
+      was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
+
+      block_input ();
       if (want_double_buffering != was_double_buffered)
        {
+         /* Force XftDraw etc to be recreated with the new double
+            buffered drawable.  */
          font_drop_xrender_surfaces (f);
 
          /* Scroll bars decide whether or not to use a back buffer
@@ -860,9 +862,10 @@ x_set_inhibit_double_buffering (struct frame *f,
           SET_FRAME_GARBAGED (f);
           font_drop_xrender_surfaces (f);
         }
+      unblock_input ();
     }
-  unblock_input ();
 }
+#endif
 
 /**
  * x_set_undecorated:
@@ -3548,8 +3551,11 @@ xic_set_xfontset (struct frame *f, const char *base_fontname)
 void
 x_mark_frame_dirty (struct frame *f)
 {
-  if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
+#ifdef HAVE_XDBE
+  if (FRAME_X_DOUBLE_BUFFERED_P (f)
+      && !FRAME_X_NEED_BUFFER_FLIP (f))
     FRAME_X_NEED_BUFFER_FLIP (f) = true;
+#endif
 }
 
 static void
@@ -3630,12 +3636,12 @@ tear_down_x_back_buffer (struct frame *f)
 void
 initial_set_up_x_back_buffer (struct frame *f)
 {
-  block_input ();
   eassert (FRAME_X_WINDOW (f));
   FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
-  if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
+
+  if (NILP (CDR (Fassq (Qinhibit_double_buffering,
+                       f->param_alist))))
     set_up_x_back_buffer (f);
-  unblock_input ();
 }
 
 #if defined HAVE_XINPUT2
@@ -8614,7 +8620,12 @@ DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
      (Lisp_Object frame)
 {
   struct frame *f = decode_live_frame (frame);
+
+#ifdef HAVE_XDBE
   return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
+#else
+  return Qnil;
+#endif
 }
 
 \f
@@ -9360,7 +9371,11 @@ frame_parm_handler x_frame_parm_handlers[] =
   gui_set_alpha,
   x_set_sticky,
   x_set_tool_bar_position,
+#ifdef HAVE_XDBE
   x_set_inhibit_double_buffering,
+#else
+  NULL,
+#endif
   x_set_undecorated,
   x_set_parent_frame,
   x_set_skip_taskbar,
index e27c6cf3146107a305f7e17e3cf8fa1a9d9ab7b3..31fb877c35bab4480424c3fc9a39358e922b293c 100644 (file)
@@ -643,18 +643,23 @@ xftfont_end_for_frame (struct frame *f)
   return 0;
 }
 
-/* When using X double buffering, the XftDraw structure we build
-   seems to be useless once a frame is resized, so recreate it on
+/* When using X double buffering, the XRender surfaces we create seem
+   to become useless once the window acting as the front buffer is
+   resized for an unknown reason (X server bug?), so recreate it on
    ConfigureNotify and in some other cases.  */
 
+#ifdef HAVE_XDBE
 static void
 xftfont_drop_xrender_surfaces (struct frame *f)
 {
-  block_input ();
   if (FRAME_X_DOUBLE_BUFFERED_P (f))
-    xftfont_end_for_frame (f);
-  unblock_input ();
+    {
+      block_input ();
+      xftfont_end_for_frame (f);
+      unblock_input ();
+    }
 }
+#endif
 
 static bool
 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
@@ -741,35 +746,37 @@ static void syms_of_xftfont_for_pdumper (void);
 struct font_driver const xftfont_driver =
   {
     /* We can't draw a text without device dependent functions.  */
-  .type = LISPSYM_INITIALLY (Qxft),
-  .get_cache = xfont_get_cache,
-  .list = xftfont_list,
-  .match = xftfont_match,
-  .list_family = ftfont_list_family,
-  .open_font = xftfont_open,
-  .close_font = xftfont_close,
-  .prepare_face = xftfont_prepare_face,
-  .done_face = xftfont_done_face,
-  .has_char = xftfont_has_char,
-  .encode_char = xftfont_encode_char,
-  .text_extents = xftfont_text_extents,
-  .draw = xftfont_draw,
-  .get_bitmap = ftfont_get_bitmap,
-  .anchor_point = ftfont_anchor_point,
+    .type = LISPSYM_INITIALLY (Qxft),
+    .get_cache = xfont_get_cache,
+    .list = xftfont_list,
+    .match = xftfont_match,
+    .list_family = ftfont_list_family,
+    .open_font = xftfont_open,
+    .close_font = xftfont_close,
+    .prepare_face = xftfont_prepare_face,
+    .done_face = xftfont_done_face,
+    .has_char = xftfont_has_char,
+    .encode_char = xftfont_encode_char,
+    .text_extents = xftfont_text_extents,
+    .draw = xftfont_draw,
+    .get_bitmap = ftfont_get_bitmap,
+    .anchor_point = ftfont_anchor_point,
 #ifdef HAVE_LIBOTF
-  .otf_capability = ftfont_otf_capability,
+    .otf_capability = ftfont_otf_capability,
 #endif
-  .end_for_frame = xftfont_end_for_frame,
+    .end_for_frame = xftfont_end_for_frame,
 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
-  .shape = xftfont_shape,
+    .shape = xftfont_shape,
 #endif
 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
-  .get_variation_glyphs = ftfont_variation_glyphs,
+    .get_variation_glyphs = ftfont_variation_glyphs,
+#endif
+    .filter_properties = ftfont_filter_properties,
+    .cached_font_ok = xftfont_cached_font_ok,
+    .combining_capability = ftfont_combining_capability,
+#ifdef HAVE_XDBE
+    .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
 #endif
-  .filter_properties = ftfont_filter_properties,
-  .cached_font_ok = xftfont_cached_font_ok,
-  .combining_capability = ftfont_combining_capability,
-  .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
   };
 #ifdef HAVE_HARFBUZZ
 struct font_driver xfthbfont_driver;
index 517869dde34f647539693ac644987ad70dd76f1d..adfe90522d445491722dc49f060b5e4cfe9f6d90 100644 (file)
@@ -3780,6 +3780,7 @@ x_flush (struct frame *f)
   unblock_input ();
 }
 
+#ifdef HAVE_XDBE
 static void
 x_drop_xrender_surfaces (struct frame *f)
 {
@@ -3795,6 +3796,7 @@ x_drop_xrender_surfaces (struct frame *f)
     }
 #endif
 }
+#endif
 
 #ifdef HAVE_XRENDER
 void
@@ -5127,9 +5129,14 @@ x_clear_window (struct frame *f)
   x_end_cr_clip (f);
 #else
 #ifndef USE_GTK
-  if (FRAME_X_DOUBLE_BUFFERED_P (f) || (f->alpha_background != 1.0))
+  if (f->alpha_background != 1.0
+#ifdef HAVE_XDBE
+      || FRAME_X_DOUBLE_BUFFERED_P (f)
 #endif
-    x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
+      )
+#endif
+    x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f),
+                 FRAME_PIXEL_HEIGHT (f));
 #ifndef USE_GTK
   else
     XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
@@ -5456,13 +5463,15 @@ x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
 /* Show the frame back buffer.  If frame is double-buffered,
    atomically publish to the user's screen graphics updates made since
    the last call to show_back_buffer.  */
+
+#ifdef HAVE_XDBE
 static void
 show_back_buffer (struct frame *f)
 {
   block_input ();
+
   if (FRAME_X_DOUBLE_BUFFERED_P (f))
     {
-#ifdef HAVE_XDBE
 #ifdef USE_CAIRO
       cairo_t *cr = FRAME_CR_CONTEXT (f);
       if (cr)
@@ -5473,13 +5482,12 @@ show_back_buffer (struct frame *f)
       swap_info.swap_window = FRAME_X_WINDOW (f);
       swap_info.swap_action = XdbeCopied;
       XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
-#else
-      eassert (!"should have back-buffer only with XDBE");
-#endif
     }
   FRAME_X_NEED_BUFFER_FLIP (f) = false;
+
   unblock_input ();
 }
+#endif
 
 /* Updates back buffer and flushes changes to display.  Called from
    minibuf read code.  Note that we display the back buffer even if
@@ -5488,8 +5496,10 @@ static void
 x_flip_and_flush (struct frame *f)
 {
   block_input ();
+#ifdef HAVE_XDBE
   if (FRAME_X_NEED_BUFFER_FLIP (f))
     show_back_buffer (f);
+#endif
   x_flush (f);
   unblock_input ();
 }
@@ -5538,8 +5548,12 @@ XTframe_up_to_date (struct frame *f)
   eassert (FRAME_X_P (f));
   block_input ();
   FRAME_MOUSE_UPDATE (f);
-  if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
+
+#ifdef HAVE_XDBE
+  if (!buffer_flipping_blocked_p ()
+      && FRAME_X_NEED_BUFFER_FLIP (f))
     show_back_buffer (f);
+#endif
 
 #ifdef HAVE_XSYNC
 #ifndef HAVE_GTK3
@@ -5592,12 +5606,14 @@ XTframe_up_to_date (struct frame *f)
   unblock_input ();
 }
 
+#ifdef HAVE_XDBE
 static void
 XTbuffer_flipping_unblocked_hook (struct frame *f)
 {
   if (FRAME_X_NEED_BUFFER_FLIP (f))
     show_back_buffer (f);
 }
+#endif
 
 /**
  * x_clear_under_internal_border:
@@ -8716,8 +8732,11 @@ x_clear_area (struct frame *f, int x, int y, int width, int height)
   x_end_cr_clip (f);
 #else
 #ifndef USE_GTK
-  if (FRAME_X_DOUBLE_BUFFERED_P (f)
-      || f->alpha_background != 1.0)
+  if (f->alpha_background != 1.0
+#ifdef HAVE_XDBE
+      || FRAME_X_DOUBLE_BUFFERED_P (f)
+#endif
+      )
 #endif
     {
 #if defined HAVE_XRENDER && \
@@ -13738,7 +13757,9 @@ x_net_wm_state (struct frame *f, Window window)
   store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
 }
 
-/* Flip back buffers on FRAME if it has undrawn content.  */
+/* Flip back buffers on F if it has undrawn content.  */
+
+#ifdef HAVE_XDBE
 static void
 flush_dirty_back_buffer_on (struct frame *f)
 {
@@ -13749,6 +13770,7 @@ flush_dirty_back_buffer_on (struct frame *f)
     show_back_buffer (f);
   unblock_input ();
 }
+#endif
 
 #ifdef HAVE_GTK3
 void
@@ -14707,8 +14729,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                  SET_FRAME_ICONIFIED (f, false);
                }
 
+#ifdef HAVE_XDBE
              if (FRAME_X_DOUBLE_BUFFERED_P (f))
                 x_drop_xrender_surfaces (f);
+#endif
               f->output_data.x->has_been_visible = true;
               SET_FRAME_GARBAGED (f);
               unblock_input ();
@@ -14753,8 +14777,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
             }
 
+#ifdef HAVE_XDBE
           if (!FRAME_GARBAGED_P (f))
             show_back_buffer (f);
+#endif
         }
       else
         {
@@ -14802,7 +14828,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef USE_GTK
          x_clear_under_internal_border (f);
 #endif
+#ifdef HAVE_XDBE
          show_back_buffer (f);
+#endif
         }
 #ifdef USE_X_TOOLKIT
       else
@@ -16016,8 +16044,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
          for size changes: that's not sufficient.  We miss some
          surface invalidations and flicker.  */
       block_input ();
+#ifdef HAVE_XDBE
       if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
         x_drop_xrender_surfaces (f);
+#endif
       unblock_input ();
 #if defined USE_CAIRO && !defined USE_GTK
       if (f)
@@ -19447,11 +19477,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
      redisplay.  To ensure that these changes become visible, draw
      them here.  */
 
+#ifdef HAVE_XDBE
   if (f)
     flush_dirty_back_buffer_on (f);
 
   if (any && any != f)
     flush_dirty_back_buffer_on (any);
+#endif
   return count;
 }
 
@@ -24309,7 +24341,9 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->update_end_hook = x_update_end;
   terminal->read_socket_hook = XTread_socket;
   terminal->frame_up_to_date_hook = XTframe_up_to_date;
+#ifdef HAVE_XDBE
   terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
+#endif
   terminal->defined_color_hook = x_defined_color;
   terminal->query_frame_background_color = x_query_frame_background_color;
   terminal->query_colors = x_query_colors;
index 65349834c9b2e006297cb7dcf793c9b2a85fd48d..80b571379813bf2af04db1c81663a1df826b2f8d 100644 (file)
@@ -1025,13 +1025,15 @@ extern void x_mark_frame_dirty (struct frame *f);
    code after any drawing command, but we can run code whenever
    someone asks for the handle necessary to draw.  */
 #define FRAME_X_DRAWABLE(f)                             \
-  (x_mark_frame_dirty((f)), FRAME_X_RAW_DRAWABLE ((f)))
+  (x_mark_frame_dirty ((f)), FRAME_X_RAW_DRAWABLE ((f)))
 
+#ifdef HAVE_XDBE
 #define FRAME_X_DOUBLE_BUFFERED_P(f)            \
   (FRAME_X_WINDOW (f) != FRAME_X_RAW_DRAWABLE (f))
 
 /* Return the need-buffer-flip flag for frame F.  */
 #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