flypig.co.uk

List items

Items from the current list are shown below.

Blog

9 Apr 2024 : Day 211 #
I've been talking about wrapping up my investigation of offscreen rendering initialisation for several days now, so I really ought to pull my finger out and actually move on. It's just, as I look through the code, I keep on finding new things to check. All of them have provided a little more insight, but none of them have resulted in a working renderer.

Today I stumbled on a new thing to check. The code that swaps the buffer is an obvious area where things might be going wrong. And since there's not much of it and it all happens within the CompositorOGL::EndFrame() method in both versions (which, incidentally, share the same code almost identically) it seemed worth spending the time to check it.

So first up the actual code that swaps the buffers. The idea is that the previous rendered frame is held in one buffer; the next frame is rendered off screen and then swapped out for the old one. This ensures the swap happens fast, minimising the chance of artefacts and flicker appearing during the render cycle.

Here's a copy of the method for reference.
bool GLContextEGL::SwapBuffers() {
  EGLSurface surface =
      mSurfaceOverride != EGL_NO_SURFACE ? mSurfaceOverride : mSurface;
  if (surface) {
    if ((mEgl->IsExtensionSupported(
             GLLibraryEGL::EXT_swap_buffers_with_damage) ||
         mEgl->IsExtensionSupported(
             GLLibraryEGL::KHR_swap_buffers_with_damage))) {
      std::vector<EGLint> rects;
      for (auto iter = mDamageRegion.RectIter(); !iter.Done(); iter.Next()) {
        const IntRect& r = iter.Get();
        rects.push_back(r.X());
        rects.push_back(r.Y());
        rects.push_back(r.Width());
        rects.push_back(r.Height());
      }
      mDamageRegion.SetEmpty();
      return mEgl->fSwapBuffersWithDamage(mEgl->Display(), surface,
                                          rects.data(), rects.size() / 4);
    }
    return mEgl->fSwapBuffers(mEgl->Display(), surface);
  } else {
    return false;
  }
}
Stepping through the code on ESR 78 this is what we get:
Thread 36 &quot;Compositor&quot; hit Breakpoint 1, mozilla::gl::GLContextEGL::
    SwapBuffers (this=0x7eac109140)
    at gfx/gl/GLContextProviderEGL.cpp:643
643     bool GLContextEGL::SwapBuffers() {
(gdb) n
[Thread 0x7fa4afe9a0 (LWP 24091) exited]
644       EGLSurface surface =
(gdb) n
[New Thread 0x7fa467c9a0 (LWP 24117)]
646       if (surface) {
(gdb) p surface
$1 = (EGLSurface) 0x7eac004170
(gdb) n
647         if ((mEgl->IsExtensionSupported(
(gdb) n
415     /opt/cross/aarch64-meego-linux-gnu/include/c++/8.3.0/bitset: No such 
    file or directory.
(gdb) 
663         return mEgl->fSwapBuffers(mEgl->Display(), surface);
(gdb) 
The really important thing to notice about this is that the condition checking support for EXT_swap_buffers_with_damage or KHR_swap_buffers_with_damage both fail. This means that the condition is skipped rather than being entered. You may recall that back on Day 83 we had to explicitly disable these two extensions and that it was the act of disabling them that resulted in the onscreen render pipeline working successfully for the first time.

It's therefore an obvious concern that this might be causing problems for the offscreen render pipeline as well. Clearly on ESR 78 these are disabled, but are they on ESR 91? Here's what we get when we try with ESR 91:
Thread 37 &quot;Compositor&quot; hit Breakpoint 1, mozilla::gl::GLContextEGL::
    SwapBuffers (this=0x7ee019aa50)
    at gfx/gl/GLContextProviderEGL.cpp:662
662     bool GLContextEGL::SwapBuffers() {
(gdb) n
663       EGLSurface surface =
(gdb) 
665       if (surface) {
(gdb) p surface
$1 = (EGLSurface) 0x7ee0004b60
(gdb) n
[Thread 0x7f1f2fe7e0 (LWP 958) exited]
666         if ((mEgl->IsExtensionSupported(
(gdb) 
415     include/c++/8.3.0/bitset: No such file or directory.
(gdb) 
682         return mEgl->fSwapBuffers(surface);
(gdb) 
This is almost identical to the ESR 78 output and crucially the extension condition is also being skipped. So I guess it's not this that's causing the problems for the offscreen render. Nonetheless I'm glad I checked.

While stepping through this I noticed that when stepping out of the SwapBuffers() method I end up in the CompositorOGL::EndFrame() method. This is also a pretty simple and linear method, so I figure it might be worth checking it as well. So that's what I'm going to do.

Here's the output from the ESR 78 code for CompositorOGL::EndFrame(). I've cut some of the output for brevity.
Thread 36 &quot;Compositor&quot; hit Breakpoint 3, mozilla::layers::
    CompositorOGL::EndFrame (this=0x7eac003450)
    at gfx/layers/opengl/CompositorOGL.cpp:2000
2000    void CompositorOGL::EndFrame() {
(gdb) n
2001      AUTO_PROFILER_LABEL(&quot;CompositorOGL::EndFrame&quot;, GRAPHICS);
(gdb) n
2022      mShouldInvalidateWindow = false;
(gdb) n
2024      if (mTarget) {
(gdb) p mTarget
$4 = {mRawPtr = 0x0}
(gdb) n
2034      mWindowRenderTarget = nullptr;
(gdb) n
2035      mCurrentRenderTarget = nullptr;
(gdb) n
2037      if (mTexturePool) {
(gdb) p mTexturePool
$5 = {mRawPtr = 0x0}
(gdb) n
2043      mGLContext->SetDamage(mCurrentFrameInvalidRegion);
(gdb) n
2044      mGLContext->SwapBuffers();
(gdb) n
2045      mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
(gdb) n
2049        mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
(gdb) n
2050        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
(gdb) n
2051        if (!mGLContext->IsGLES()) {
(gdb) n
258     obj-build-mer-qt-xr/dist/include/GLContext.h: No such file or directory.
[...]
(gdb) n
2056      mCurrentFrameInvalidRegion.SetEmpty();
(gdb) n
2058      Compositor::EndFrame();
(gdb)
And here's the same on ESR 91. Once again, the execution flow, variables and output overall are almost identical.
Thread 37 &quot;Compositor&quot; hit Breakpoint 2, mozilla::layers::
    CompositorOGL::EndFrame (this=0x7ee0002f10)
    at gfx/layers/opengl/CompositorO
GL.cpp:2014
2014    void CompositorOGL::EndFrame() {
(gdb) n
2015      AUTO_PROFILER_LABEL(&quot;CompositorOGL::EndFrame&quot;, GRAPHICS);
(gdb) n
2035      mFrameInProgress = false;
(gdb) n
2036      mShouldInvalidateWindow = false;
(gdb) n
2038      if (mTarget) {
(gdb) p mTarget
$2 = {mRawPtr = 0x0}
(gdb) n
2048      mWindowRenderTarget = nullptr;
(gdb) n
2049      mCurrentRenderTarget = nullptr;
(gdb) n
2051      if (mTexturePool) {
(gdb) p mTexturePool
$3 = {mRawPtr = 0x0}
(gdb) n
2057      mGLContext->SetDamage(mCurrentFrameInvalidRegion);
(gdb) n
2058      mGLContext->SwapBuffers();
(gdb) n
2059      mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
(gdb) n
2063        mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
(gdb) n
2064        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
(gdb) n
2065        if (!mGLContext->IsGLES()) {
(gdb) n
260     ${PROJECT}/obj-build-mer-qt-xr/dist/include/GLContext.h: No such file 
    or directory.
[...]
(gdb) n
2070      mCurrentFrameInvalidRegion.SetEmpty();
(gdb) n
[...]
2072      Compositor::EndFrame();
(gdb)                              
That's all good. Both match up nicely as we might hope. With that dealt with it now really does feel like it's time to move on. To cement this segue I've set the ESR 91 build running. This will allow me to check the changes I made over the last few days to the GetAppDisplay() usage. For some reason every night for the last few nights I've forgotten to run the build which has prevented me from checking it.

What would be great is if this build were to complete before the end of today because I want to run a new build of ESR 78 overnight. Rebuilding ESR 78 might sound a little crazy, after all I should be focusing on ESR 91. But as I've previously explained, I want to test out rendering to the background in different colours to establish more accurately where rendering is failing. Every thing I've tried up to now has had no effect on the output, but that's all been using ESR 91. I want to test the same things on ESR 78. That means making minimal changes to the ESR 78 code and doing a rebuild to test it on-device.

I can't think of a better way of doing this. I've come to the conclusion I just can't get the same results using the debugger alone. And so it is that I need to rebuild ESR 78.

With all these builds and plans for builds, I won't be able to do much more work on this today, so onward into the week to see how things progress.

If you'd like to read any of my other gecko diary entries, they're all available on my Gecko-dev Diary page.

Comments

Uncover Disqus comments