From: Daniel Colascione <dancol@dancol.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: RFC: flicker-free double-buffered Emacs under X11
Date: Fri, 21 Oct 2016 11:27:29 -0700 [thread overview]
Message-ID: <r025zilxsgku.fsf@dancol.org> (raw)
In-Reply-To: <831sz9sime.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 21 Oct 2016 20:43:21 +0300")
Eli Zaretskii <eliz@gnu.org> writes:
>> Cc: emacs-devel@gnu.org
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Fri, 21 Oct 2016 04:04:21 -0700
>>
>> > Also, the call to font_flush_frame_caches is unconditional, although
>> > only one font back-end supports it. That seems to incur a gratuitous
>> > overhead of a function call for the other font back-ends.
>>
>> We're testing whether the hook function is non-NULL before calling into
>> it, so only that one backend gets the call. In any case, the overhead is
>> trivial --- it's one indirect function call compared to all of
>> redisplay. (Every call into a shared library is the same indirect jump.)
>
> The code is more clear with the test before the call, otherwise the
> code reader needs to look in the hook to understand when it's a no-op.
But the test (of whether the hook exists) _is_ before the call. What are
you proposing?
some_backend_needs_flush = False
for backend in font_back_ends:
if has_flush_hook(backend):
some_back_end_needs_flush = True
if some_back_end_needs_flush:
for backend in font_back_ends:
if has_flush_hook(backend):
backend.flush_hook()
That's silly. Can you elaborate on what you consider a cleaner approach?
> So I'd prefer to have the test outside of the call, or even outside of
> the loop.
See below. I don't think that giving font back-ends an opportunity to do
_something_ in response to a frame being garbaged in certain ways is a
bad thing.
>> >> + FOR_EACH_FRAME (tail, frame)
>> >> + {
>> >> + struct frame *f = XFRAME (frame);
>> >> + if (FRAME_TERMINAL (f)->redisplay_end_hook)
>> >> + (*FRAME_TERMINAL (f)->redisplay_end_hook) (f);
>> >> + }
>> >
>> > This will call the hook for each frame, every redisplay cycle. By
>> > contrast, redisplay_internal many times updates only the selected
>> > window of the selected frame. Is calling the hook for all the frames
>> > really needed, or should we only call it for the selected frame in the
>> > latter case, or maybe just for frames that got updated?
>>
>> The hook only does something in the case where someone called update_end
>> and we demurred on actually flipping the buffer because we knew we were
>> in redisplay and would be getting redisplay_end_hook shortly. That is,
>> if we update only one frame, we're only going to do one buffer flip.
>
> That might be so, but what you say above is in no way apparent from
> looking at the code. IME, it is very important to have the idea when
> something is being done and when not just by looking at the code in
> redisplay_internal; having to find that out by realizing that some
> flag is set in update_end and then tested in the hook makes the code
> more subtle and its maintenance harder. It's not like keeping this
> detail from redisplay_internal makes this detail local to some
> functions, or somesuch, so there's really no reason to conceal it,
> IMO.
This sentiment strikes me as being analogous to the old "no use of hooks
in Emacs internals" line --- yet we have facilities like syntax-ppss
that rely on hooks in core, and it's worked out fine.
We need to do a buffer flip at the end of redisplay for each frame on
which update_end was called during redisplay. If someone calls
update_end _outside_ redisplay, we should do a buffer flip
immediately. The code I've sent is the cleanest way of implementing this
model short of changing how update_begin and update_end work.
I think thhat what you're proposing is a layering violation. It will
make maintenance harder. The only facility that cares about the
has-a-frame-been-updated state is the X11 double-buffered back-end, so
making xdisp track this state makes everything more complicated,
especially because xdisp already has a "needs redisplay" flag and
shouldn't need to keep track of a separate "needs buffer flip" flag.
It shouldn't have to care. That's not its job.
>> Or are you worried about the function call overhead? That, as I
>> mentioned above, is trivial.
>
> No, I worry about maintainability of the display code and about
> lowering the risk of bugs introduced due to such subtleties.
>
I'm also worried about maintainability: that's why I don't want to make
redisplay_internal any more of a big ball of mud than it already is. I
think it's cleaner to have xterm keep track of state only xterm needs.
>> > Also, should
>> > we distinguish between visible and iconified frames?
>>
>> If we do, we should do it in the code that performs the updates, not the
>> code (the snippet immediately above) that publishes the updates we've
>> already done.
>
> See above: I don't like such dependencies and find them in general an
> obstacle to understanding the overall logic of the display code. I
> don't mind adding a test in update_frame and friends, but that
> shouldn't prevent us from having a similar (or even identical) test
> here.
What dependency? You're proposing adding a lot of complexity to the loop
that calls redisplay_end_hook, and I still have no idea what this
complexity is supposed to accomplish.
>
>> >> +#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);
>> >
>> > Shouldn't we turn off the supports_xdbe flag in the case of failure?
>>
>> supports_xdbe is whether XDBE is supported on a connection at all. What
>> if XdbeAllocateBackBufferName fails transiently?
>
> How can it fail transiently? And why turning off supports_xdbe in
> that case would mean trouble?
It's an allocation. Allocations can fail. And XDBE isn't guaranteed to
work for all visuals.
>
>> >> +#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
>> >
>> > No need for braces here, since we now require a C99 compiler.
>>
>> If we put xdbe_major and xdbe_minor at function level, the names leak
>> into function scope. With braces, they exist only around the call to
>> XdbeQueryExtension
>
> We use that in many other places, so I think these precautions are
> misguided and generally make our coding style less apparent.
Fine.
next prev parent reply other threads:[~2016-10-21 18:27 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=r025zilxsgku.fsf@dancol.org \
--to=dancol@dancol.org \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.