summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-05-03 09:22:06 +0800
committerPo Lu <luangruo@yahoo.com>2022-05-03 09:22:06 +0800
commit952cc28e58eafbdd409bf36f9ca656dae533542b (patch)
treef51c18a73cff22d3b0b8294430b838cf59efbff6
parent64bcfcbd322d4fdb78c7d7dd0748dabc0e0b2cbc (diff)
Clean up X11 double buffering code
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.
-rw-r--r--src/xfns.c39
-rw-r--r--src/xftfont.c63
-rw-r--r--src/xterm.c54
-rw-r--r--src/xterm.h4
4 files changed, 109 insertions, 51 deletions
diff --git a/src/xfns.c b/src/xfns.c
index 7176d626094..14721c6ce83 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -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
}
@@ -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,
diff --git a/src/xftfont.c b/src/xftfont.c
index e27c6cf3146..31fb877c35b 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -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;
diff --git a/src/xterm.c b/src/xterm.c
index 517869dde34..adfe90522d4 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -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;
diff --git a/src/xterm.h b/src/xterm.h
index 65349834c9b..80b57137981 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -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