From: Alan Third <alan@idiocy.org>
To: Aaron Jensen <aaronjensen@gmail.com>
Cc: Po Lu <luangruo@yahoo.com>, Kai Ma <justksqsf@gmail.com>,
Eli Zaretskii <eliz@gnu.org>,
63187@debbugs.gnu.org
Subject: bug#63187: 30.0.50; Tail of longer lines painted after end of nearby lines on macOS
Date: Sun, 25 Jun 2023 13:46:03 +0100 [thread overview]
Message-ID: <ZJg3C/98QHEzLRfI@idiocy.org> (raw)
In-Reply-To: <CAHyO48wF6t4-SV9pCkQYPt8Cjiqu9ndKfqb_i8+Hgq=FDmGRGg@mail.gmail.com>
On Sat, Jun 24, 2023 at 05:43:04PM -0400, Aaron Jensen wrote:
> On Sat, Jun 24, 2023 at 5:29 PM Alan Third <alan@idiocy.org> wrote:
> > My suspicion is that if we try to swap between the buffers too fast,
> > something is going wrong between the process of flushing the drawing
> > to the pixel buffer and copying the pixel buffer to the next one.
>
> Do we have any way to know when the flush is done? In other words, can
> we only return the surface to the pool after that? Or is that already
> done?
No. Part of the reason I'm very unsure about this idea is that Apple
are very clear that they don't think you should ever have to deal with
this sort of thing.
The provide functions that allow you to force the flush, but then they
say you should never have to use it.
How the macOS graphics system works is also pretty much undocumented,
so it's hard to get to grips with whether anything *is* going wrong
here. A lot of people do seem to have a deep understanding of it, but
I don't have the first clue how you go about learning from first
principles.
> > So, we have two buffers, A and B. We draw to A, but before we're done
> > the system calls display. We send off the incomplete buffer A to VRAM,
> > and then take a copy of that incomplete buffer for B. At some point
> > the system decides to flush the graphics context to the buffer, but
> > it's flushing to A, and we've *already* copied A to B.
>
> Can we avoid sending incomplete buffers? What is "done"? I don't know
> much about graphics programming but I imagine we don't want to send
> incomplete buffers ever, we want to finish painting the whole buffer,
> then send it. I think I'm also missing understanding on what it means
> to flush the graphics context to the buffer. Is that the drawing that
> we're doing (like rendering text/etc?) I feel like I may need a
> whiteboard session or something to get my head around this so that I
> can be of any assistance other than asking dumb questions :)
When I say "done", I largely mean a call to ns_update_end. So most,
but not all iiuc, Emacs drawing is done between a call to
ns_update_begin and a call to ns_update_end.
Apple recommend you leave the final display to screen to them. At some
point, when the system decides it wants to update the screen, it
checks if we've marked the view's needsDisplay variable to true, and
if so, amongst a lot of other stuff, it calls our display function.
Now, I think this, for the most part, only happens within the NS
runloop, but it is possible to force it. I think Apple are right,
though, and we don't want to force it unless we really need to.
As for flushing the context, this is another thing Apple say we
shouldn't touch, but they do give you the tools to force it.
Imagine you want to draw some text, then a line, then a circle, or
whatever. You'd think the system would draw them directly to the
buffer as you call the functions, but apparently the system can queue
them up and apply them in one go later on. I believe this should
happen when we release the context, or in various other situations, so
it's not something I really think is likely to be the cause, but it
does sort-of match what we see happening.
> > Who knows. Maybe all we need to do is make sure we don't try to draw
> > to the screen while emacs is drawing to the buffer... Something like
> > this:
> >
> > modified src/nsterm.m @@ -10622,7 +10622,7 @@ - (void) display
> > {
> > NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "[EmacsLayer display]");
> >
> > - if (context)
> > + if (context && context != [NSGraphicsContext currentContext])
> > {
> > [self releaseContext];
> >
> >
> > ...
> >
> > Actually...
> >
> > That change should probably be made anyway. If the NS run loop kicks
> > in between an ns_focus call and an ns_unfocus call, it could call
> > display and our display function will happily destroy the existing
> > context without creating a new one, so any *subsequent* drawing
> > operations, up until ns_unfocus, will be lost.
>
> OK, I'm adding this to my current build.
>
> Is this in line with the type of issue I'm seeing where scrolling
> works but the ghosting either replicates (or scrolls with it?) In
> other words, what would you expect to see in this scenario? Would it
> just stop painting entirely?
It could be. The more I think about this change, the more I think it
might be the solution.
If you imagine we call ns_update_begin, which creates the
context/buffer/whatever else we need, then somewhere in the midst of
drawing display is called and the context is wiped out and the buffer
is sent off to the screen. Until ns_update_end is called (or anything
else that happens to call getContext, like copyRect) then nothing will
be drawn to the buffer, even though Emacs reasonably expects it has.
So yes, this might mean some parts of the screen aren't cleared, but
it could also mean other drawing actions don't take place, like
actually drawing text, or drawing underlines or whatever.
HOWEVER, as I said above, copyRect calls getContext, so if we then try
to scroll, it *will* draw to the buffer. CopyRect will *always*
successfully draw to a buffer, even if some drawing actions will have
failed already.
All my change above does is make sure that the currently selected
context (i.e. the one we're drawing to right this moment) isn't the
same one we're trying to display. unlockFocus always clears the
current context so if the current view is focused, the new check
should catch it, and if it's not, say we're drawing to another frame
or not drawing at all, then it should let it be displayed.
The biggest risk is we start missing our chance to display the buffer
to the screen, because it just skips sending the buffer. If you start
seeing delays in the screen updating then we may have to consider
forcing updates in ns_update_end or something.
I hope this fixes it. It looks like a legitimate mistake in my logic
whereas practically every other thing I can think of requires some
weird behaviour in AppKit.
Kai, it might be worth trying just that change above, while keeping
the call to performSelectorInMainThread and see if it fixes anything
for you.
--
Alan Third
next prev parent reply other threads:[~2023-06-25 12:46 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <m2fs8histt.fsf@gmail.com>
2023-04-30 10:33 ` bug#63187: 30.0.50; Tail of longer lines painted after end of nearby lines on macOS Eli Zaretskii
2023-04-30 10:46 ` Aaron Jensen
2023-04-30 13:25 ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-04-30 14:25 ` Aaron Jensen
2023-04-30 14:42 ` Eli Zaretskii
2023-04-30 14:57 ` Aaron Jensen
2023-04-30 15:26 ` Eli Zaretskii
2023-04-30 16:48 ` Aaron Jensen
2023-04-30 19:04 ` Eli Zaretskii
2023-04-30 23:58 ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-05-01 12:40 ` Eli Zaretskii
2023-05-01 13:18 ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-05-01 13:25 ` Eli Zaretskii
2023-05-01 13:47 ` Aaron Jensen
2023-05-01 13:52 ` Eli Zaretskii
2023-05-01 13:55 ` Aaron Jensen
2023-05-01 14:06 ` Aaron Jensen
2023-05-09 3:07 ` Aaron Jensen
2023-05-09 5:39 ` Eli Zaretskii
2023-05-13 13:54 ` Eli Zaretskii
2023-05-13 14:23 ` Aaron Jensen
2023-05-18 11:21 ` Eli Zaretskii
2023-05-18 15:59 ` Aaron Jensen
2023-06-08 5:40 ` Kai Ma
2023-06-08 7:33 ` Kai Ma
2023-06-08 12:51 ` Alan Third
2023-06-08 13:42 ` Kai Ma
2023-06-08 14:57 ` Kai Ma
2023-06-08 17:22 ` Alan Third
2023-06-09 2:42 ` Kai Ma
2023-06-09 2:47 ` Aaron Jensen
2023-06-09 3:12 ` Kai Ma
2023-06-09 18:27 ` Alan Third
2023-06-09 18:46 ` Aaron Jensen
2023-06-09 20:00 ` Alan Third
2023-06-12 13:04 ` Aaron Jensen
2023-06-16 2:17 ` Aaron Jensen
2023-06-19 15:46 ` Aaron Jensen
2023-06-24 4:17 ` Kai Ma
2023-06-24 13:34 ` Aaron Jensen
2023-06-24 14:14 ` Alan Third
2023-06-24 14:52 ` Aaron Jensen
2023-06-24 15:08 ` Eli Zaretskii
2023-06-24 15:41 ` Alan Third
2023-06-24 16:05 ` Aaron Jensen
2023-06-24 21:29 ` Alan Third
2023-06-24 21:43 ` Aaron Jensen
2023-06-25 12:46 ` Alan Third [this message]
2023-06-25 17:07 ` Aaron Jensen
2023-06-25 18:17 ` Alan Third
2023-06-25 19:07 ` Aaron Jensen
2023-06-25 21:18 ` Alan Third
2023-06-25 22:33 ` Aaron Jensen
2023-06-26 7:27 ` Kai Ma
2023-06-28 19:53 ` Alan Third
2023-07-21 2:02 ` Aaron Jensen
2023-07-23 11:20 ` Alan Third
2023-07-23 13:01 ` Aaron Jensen
2023-07-25 14:47 ` Aaron Jensen
2023-07-25 15:45 ` Eli Zaretskii
2023-06-23 8:48 ` Alan Third
2023-06-23 11:54 ` Aaron Jensen
2023-05-01 17:26 ` Alan Third
2023-05-01 22:40 ` Aaron Jensen
2023-05-02 10:14 ` Alan Third
2023-05-02 12:21 ` Eli Zaretskii
2023-05-02 22:36 ` Alan Third
2023-05-03 8:11 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-05-03 13:08 ` Eli Zaretskii
2023-05-02 0:07 ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-05-02 0:32 ` Aaron Jensen
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=ZJg3C/98QHEzLRfI@idiocy.org \
--to=alan@idiocy.org \
--cc=63187@debbugs.gnu.org \
--cc=aaronjensen@gmail.com \
--cc=eliz@gnu.org \
--cc=justksqsf@gmail.com \
--cc=luangruo@yahoo.com \
/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.