flypig.co.uk

List items

Items from the current list are shown below.

Blog

2 Nov 2023 : Day 78 #
So, I'm back today looking now at the other end of the rendering pipeline. At the end of the day working on this yesterday I concluded I needed to do two tasks:
  1. Step through GLContextProviderEGL::CreateWrappingExisting() and the changes made in commit 51e18eb9b16ee94a.
  2. Check the unapplied patches to check whether there anything crucial missing.
Right now the first is much more appealing, so I'm going to go with that.

Putting a breakpoint on both versions works: both are triggered from nsWindow::GetGLContext() with the aDisplay set to 0x1 as expected. From this point on the actual internals of the two respective methods differ quite considerably.

The ESR 78 code passes the display to a call to GLLibraryEGL::EnsureInitialized(false, &discardFailureId, aDisplay). It then creates a GLContextEGL which it configures and returns.

The ESR 91 code gets the DefaultEglLibrary and uses it to create an EglDisplay structure, which involves passing in the aDisplay value: EglDisplay::Create(*lib.operator->(), (EGLContext)aDisplay, false). It finishes up creating a new GLContextEGL instance similar to the way ESR 78 does.

The initial step through of both each version throws up nothing unusual. For ESR 78:
1098	  if (!GLLibraryEGL::EnsureInitialized
            (false, &discardFailureId, aDisplay)) {
(gdb) n
1103	  if (!aContext || !aSurface) return nullptr;
(gdb) n
1105	  const auto& egl = GLLibraryEGL::Get();
(gdb) n
1106	  SurfaceCaps caps = SurfaceCaps::Any();
(gdb) n
1110	                       (EGLSurface)aSurface, (EGLContext)aContext);
(gdb) n
1106	  SurfaceCaps caps = SurfaceCaps::Any();
(gdb) n
1112	  gl->mOwnsContext = false;
(gdb) n
1106	  SurfaceCaps caps = SurfaceCaps::Any();
(gdb) n
1097	  nsCString discardFailureId;
(gdb) n
mozilla::embedlite::nsWindow::GetGLContext (this=0x7fb8ce4970)
    at mobile/
    sailfishos/embedshared/nsWindow.cpp:416
416	      if (!mozContext || !mozContext->Init()) {
And for ESR 91:
(gdb) n
1000      if (!aContext || !aSurface) return nullptr;
(gdb) n
1002      nsCString failureId;
(gdb) n
1003      const auto lib = gl::DefaultEglLibrary(&failureId);
(gdb) n
1004      if (!lib) {
(gdb) n
1008      const auto egl = EglDisplay::Create(*lib.operator->(),
            (EGLContext)aDisplay, false);
(gdb) n
1009      if (!egl) {
(gdb) n
1016      const auto desc = GLContextDesc{{flags}, false};
(gdb) n
1021                           (EGLSurface)aSurface, (EGLContext)aContext);
(gdb) n
1022      gl->SetIsDoubleBuffered(true);
(gdb) n
1023      gl->mOwnsContext = false;
(gdb) n
1008      const auto egl = EglDisplay::Create(*lib.operator->(),
            (EGLContext)aDisplay, false);
(gdb) n
1003      const auto lib = gl::DefaultEglLibrary(&failureId);
(gdb) n
1002      nsCString failureId;
(gdb) n
mozilla::embedlite::nsWindow::GetGLContext (this=this@entry=0x7f88580b50)
    at mobile/
    sailfishos/embedshared/nsWindow.cpp:421
421           if (!mozContext || !mozContext->Init()) {
They both bounce around a bit, but none of them drop out early due to failures or null pointers.

One obvious difference is how GLLibraryEGL::CreateDisplay() is called. In ESR 78 this happens inside the call to GLLibraryEGL::DoEnsureInitialized(). In ESR 91 this method has been renamed to GLLibraryEGL::Init() and is quite similar, apart from the fact that there is no call to GLLibraryEGL::CreateDisplay() inside it. It's notably absent.

The question I'm therefore wondering is: where, if at all, does this get called in ESR 91. I'm going to find out.

Here it is in ESR 78:
Thread 38 "Compositor" hit Breakpoint 2, mozilla::gl::GLLibraryEGL::CreateDisplay
    (this=this@entry=0x7ed81a25f0, forceAccel=forceAccel@entry=false, 
    gfxInfo=..., out_failureId=out_failureId@entry=0x7f2200e298,
    aDisplay=aDisplay@entry=0x1)
    at gfx/gl/GLLibraryEGL.cpp:760
760	                                       EGLDisplay aDisplay) {
(gdb) bt
#0  mozilla::gl::GLLibraryEGL::CreateDisplay (this=this@entry=0x7ed81a25f0,
    forceAccel=forceAccel@entry=false, gfxInfo=..., 
    out_failureId=out_failureId@entry=0x7f2200e298, aDisplay=aDisplay@entry=0x1)
    at gfx/gl/GLLibraryEGL.cpp:760
#1  0x0000007ff29106c4 in mozilla::gl::GLLibraryEGL::DoEnsureInitialized
    (this=0x7ed81a25f0, forceAccel=false, out_failureId=0x7f2200e298,
    aDisplay=0x1)
    at gfx/gl/GLLibraryEGL.cpp:578
#2  0x0000007ff2910e3c in mozilla::gl::GLLibraryEGL::DoEnsureInitialized
    (this=<optimized out>, forceAccel=<optimized out>, 
    out_failureId=<optimized out>, aDisplay=<optimized out>)
    at gfx/gl/GLLibraryEGL.cpp:403
#3  0x0000007ff2911028 in mozilla::gl::GLContextProviderEGL::
    CreateWrappingExisting (aContext=0x7ed8004e70, aSurface=0x5555ba2d70, 
    aDisplay=<optimized out>) at gfx/gl/GLContextProviderEGL.cpp:1098
But in ESR 91 it's not getting called at all. This is a potentially important difference and definitely worth digging in to further.

From the code it's possible to see how this has happened. I've even discussed it in previous posts. Essentially there was a change that meant all of the displays are created internally, rather than allowing them to be passed in externally. This is a problem for us because when it comes to the Sailfish Browser the display is created in qtmozembed and passed in from there.

In ESR 78 this display gets passed in to GLLibraryEGL::DoEnsureInitialized() (you can see it in the backtrace just earlier). Towards the end of this method there's a call like this:
  mEGLDisplay = CreateDisplay(forceAccel, gfxInfo, out_failureId, aDisplay);
  if (!mEGLDisplay) {
    return false;
  }
If aDisplay isn't set then the CreateDisplay() method does some work. But if it is set — which is the case we're interested in — then the method just returns the value that was passed in without doing anything with it.

In ESR 91 this all changed. Here things would have happened via the GLContextEGLFactory::CreateImpl() method, but this removed the ability to pass in a display.

In the code now, the EglDisplay still goes into a "create" method like this:
Thread 34 "Compositor" hit Breakpoint 4, mozilla::gl::EglDisplay::EglDisplay
    (this=0x555596e700, lib=..., disp=0x1, isWarp=false)
    at gfx/gl/GLLibraryEGL.cpp:681
681     EglDisplay::EglDisplay(const PrivateUseOnly&, GLLibraryEGL& lib,
(gdb) bt
#0  mozilla::gl::EglDisplay::EglDisplay (this=0x555596e700, lib=..., disp=0x1,
    isWarp=false)
    at gfx/gl/GLLibraryEGL.cpp:681
#1  0x0000007fba5c4260 in __gnu_cxx::new_allocator<mozilla::gl::EglDisplay>::
    construct<mozilla::gl::EglDisplay, mozilla::gl::EglDisplay::PrivateUseOnly,
    mozilla::gl::GLLibraryEGL&, void* const&, bool const&> (__p=0x555596e700,
    this=<optimized out>)
    at /srv/mer/toolings/SailfishOS-4.5.0.18/opt/cross/aarch64-meego-linux-gnu/
    include/c++/8.3.0/new:169
[...]
#9  mozilla::gl::EglDisplay::Create (lib=..., display=<optimized out>,
    display@entry=0x1, isWarp=isWarp@entry=false)
    at gfx/gl/GLLibraryEGL.cpp:676
#10 0x0000007fba5c4420 in mozilla::gl::GLContextProviderEGL::
    CreateWrappingExisting (aContext=0x7eb80041a0, aSurface=0x55559676b0,
    aDisplay=0x1)
    at gfx/gl/GLContextProviderEGL.cpp:1008
The call to the EglDisplay constructor is somewhat masked by this line:
  const auto ret =
      std::make_shared(PrivateUseOnly{}, lib, display, isWarp);
So in ESR 78 we call GLLibraryEGL::CreateDisplay() whereas in ESR 91 we call EglDisplay::Create(). Both are defined in GLLibraryEGL.cpp, but they are from different classes and do different things. What we really want is for the ESR 91 to also call GLLibraryEGL::CreateDisplay(). That method exists, although it changed so that it can't take in display values. So that's what we're going to have to change I think.

This has all become rather confusing and the different methods are swimming around in my head. I'm fairly certain that means I've reached the limit of my ability to work on this tonight. I'll have to pick it up again tomorrow.

For all the other entries in my developer diary, check out the Gecko-dev Diary page.

Comments

Uncover Disqus comments