On Jan 4, 2024, at 1:58 AM, Eli Zaretskii <eliz@gnu.org> wrote:

It is called where the 'face' property changes.  The display engine
finds the next position where that happens, and arranges for calling
face_at_buffer_position when it gets to process that position.  The
results of face merging at that position are kept in a cache, to avoid
performing it more often than needed.

This makes sense, thanks.  In the ‘face-remap property scenario, the number of such ‘face property-change positions doesn’t actually change.  But at each such position, the face-merging code would have to check for an operative ‘face-remap property at point and use it together with `face-remapping-alist' to compute the final face merge. I would expect that performance would depend on whether the face-merge cache could be (largely) preserved, even as 'face-remap properties are added/removed/moved around (typically in repetitive fashion).

I do this very thing already in indent-bars[1], globally in the buffer, using face-remapping-alist.  The performance of that remapping is incredibly good in my experience.  So fast in fact that I’ve had to introduce a timer to artificially slow it down since it leads to rapid face flashing during smooth scrolling.

How many faces do you have defined on that frame?  I'm guessing not
many, or maybe they are all almost identical (differ in only one or
two simple attributes).

Right now it’s just a couple of faces (remove one face-remap, add another).  If I had access to a ‘face-remap property, I could imagine maybe 10 faces at most being affected as point changes.  Each face would change by one or two attributes like foreground, stipple, etc.  

I’m sure there could be lots of uses of this type of functionality, but “enhance the focus on one region of importance” seems like a very common one.  For example, you might imagine dim/gray version of all the font-lock faces outside the “treesitter region of interest” and bright ones inside.  Whenever that TS-prescribed region changes, an overlay with a ‘face-remap property gets moved.