Subject: bug#37755: Logic in init_fringe_bitmap should be moved to backends (maybe rif->define_fringe_bitmap)

From: Carlos Pita <[email-masked]>
Date: Tue, 15 Oct 2019 16:04:09 -0300

(Sorry, forgot to CC debbugs, resending all together below)

Hi Eli,

I've sketched the tree of define/init calls below and I believe I
pretty much understand how the initialization sequence works now and
I'm ready to think about how to properly extend the redisplay
interface in order to include init_fringe_bitmap.

But could you check that my understanding of the flow is sound?

# On emacs startup initialize all standard bitmaps but
# postponing rif->define_fringe_bitmap until frame creation

init_fringe_once
    init_fringe_once_for_pdumper
        for each standard bitmap
            init_fringe_bitmap (oncep = 1)
                since oncep: do not try to destroy previous
                since !rif: do not rif->define_fringe_bitmap

# When a frame is created, actually call rif->define_fringe_bitmap
# for each standard bitmap and also for lisp defined
# bitmaps that were created in a daemon with no frame / rif

gui_init_fringe (I assume this is called once per frame)
    for each standard bitmap
        rif->define_fringe_bitmap
    for each additional bitmap (recently introduced by [1])
        rif->define_fringe_bitmap

# When defined from lisp do both steps at once (init and rif->define)
# except that we're in daemon with no frame / rif

define-fringe-bitmap (lisp)
   init_fringe_bitmap (oncep = 0)
      when rif && !oncep:
           since !oncep: do destroy previous (if any)
           since rif: do rif->define_fringe_bitmap (if not in daemon)

Also, I understand the roles of init_fringe_bitmap and define_fringe_bitmap as:

init_fringe_bitmap
   Initialize bitmap as far as possible without assuming there is a rif/frame
   available. For example, bit shuffling, endianness stuff.

define_fringe_bitmap
   Do the remaining, backend specific, initialization, which is now possible
   because we have a rif/frame. For example, create Cairo surfaces.

Now I see a problem here: abstracting from the platform/backend by
encapsulating platform/backend related logic in the rif is only
possible when there is a rif at hand! And there is no rif when there
is no frame. So that's probably the reason why quite a few
platform-specific assumptions have leaked into fringe.c. The sad part
is how coupled are those bit manipulations to those backends, it's not
like there is some platform-specific part first and then a
backend-specific part, because both are too intermingled and they
logically belong together.

So I'm again tempted to move init into define, I don't think there is
any real gain in splitting the initialization this way, it's not like
the initial part is time consuming or resource intensive so we better
do it ASAP or whatever and, as I've said, it neither provides an
orthogonal abstraction, there is no cartesian product of platforms and
backends here, so to speak. And part of the complexity of the
initialization sequence above is due to this split.

What do you think?

I'll be sending a patch quite soon.

---

[1] [PATCH] Fix initialization of user-defined fringe bitmaps in daemon

On Tue, Oct 15, 2019 at 6:33 AM Eli Zaretskii <[email-masked]> wrote:
>
> > From: Carlos Pita <[email-masked]>
> > Date: Mon, 14 Oct 2019 23:30:08 -0300
> >
> > In fringe.c you have init_fringe_bitmap with this structure:
> >
> > ```
> > #if defined (HAVE_X_WINDOWS)
> > ...
> > #ifdef USE_CAIRO
> > ...
> > #endif
> > ...
> > #endif
> > #ifdef HAVE_NTGUI
> > ...
> > #endif
> >   if (!once_p)
> >     {
> >     ....
> >     rif->define_fringe_bitmap (...)
> >     ....
> >     }
> > ```
> >
> > Now, this is backend specific code that should be moved behind the
> > redisplay_interface.
>
> Yes, it should.
>
> > It seems to me that the obvious candidate to host that code is
> > define_fringe_bitmap.
>
> No, I think we need another interface, as define_fringe_bitmap is used
> directly from other places.