mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-31 12:51:54 -08:00
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.
This commit is contained in:
parent
64bcfcbd32
commit
952cc28e58
4 changed files with 109 additions and 51 deletions
39
src/xfns.c
39
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
54
src/xterm.c
54
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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue