flypig.co.uk

List items

Items from the current list are shown below.

Gecko

19 Feb 2024 : Day 161 #
Yesterday I was complaining about the difficulty debugging while travelling by train. Before I'd even posted the diary entry I'd received some beautiful new creations from Thigg to illustrate my experiences. I think he's captured it rather too well and it's a real joy to be able to share this creation with you.
 
A pig with wings sitting in the storage department of a train with a laptop on its lap, entangled into way too many usb cables.

This is just so great! But although this was the most representative, it wasn't my favourite of the images Thigg created. I'll be sharing some of the others at other times when I have the pleasure of enjoying train-based-development, so watch out for more!

On to a fresh day, and this morning the package I started building yesterday evening on the train has finally finished. But that's not as helpful to me as I was hoping it would be when I kicked it off. The change I made was to annotate the code with some debug output. Since then I've been able to find out all the same information using the debugger.

To recap the situation, we've been looking at WebView rendering. Currently any attempt to use the WebView will result in a crash. That's because the the EmbedLite PuppetWdigetBase code, on discovering that the layer manager is of type LAYERS_WR (Web Renderer) is intentionally triggering a crash. It requires the layer manager to be of type LAYERS_CLIENT to prevent this crash from happening.

So my task for today is to find out where the layer manager is being created and establish why the wrong type is being used. To get a good handle on the situation I'll also need to compare this against the same paths in ESR 78 to find out whey they're different.

Looking through the code there are two obvious places where a WebLayerManager is created. First there's code in PuppetWidget that looks like this:
bool PuppetWidget::CreateRemoteLayerManager(
    const std::function<bool(LayerManager*)>& aInitializeFunc) {
  RefPtr<LayerManager> lm;
  MOZ_ASSERT(mBrowserChild);
  if (mBrowserChild->GetCompositorOptions().UseWebRender()) {
    lm = new WebRenderLayerManager(this);
  } else {
    lm = new ClientLayerManager(this);
  }
[...]
Second there's some code in nsBaseWidget that looks like this (I've left some of the comments in, since they're relevant):
already_AddRefed<LayerManager> nsBaseWidget::CreateCompositorSession(
    int aWidth, int aHeight, CompositorOptions* aOptionsOut) {
[...]
    gfx::GPUProcessManager* gpu = gfx::GPUProcessManager::Get();
    // Make sure GPU process is ready for use.
    // If it failed to connect to GPU process, GPU process usage is disabled in
    // EnsureGPUReady(). It could update gfxVars and gfxConfigs.
    gpu->EnsureGPUReady();

    // If widget type does not supports acceleration, we may be allowed to use
    // software WebRender instead. If not, then we use ClientLayerManager even
    // when gfxVars::UseWebRender() is true. WebRender could coexist only with
    // BasicCompositor.
[...]
    RefPtr<LayerManager> lm;
    if (options.UseWebRender()) {
      lm = new WebRenderLayerManager(this);
    } else {
      lm = new ClientLayerManager(this);
    }
[...]
It should be pretty easy to check using the debugger whether either of these are the relevant routes when setting up the layer manager. I still have the debugging session open from yesterday:
(gdb) break nsBaseWidget.cpp:1364
Breakpoint 3 at 0x7ff2a57b64: file widget/nsBaseWidget.cpp, line 1364.
(gdb) break PuppetWidget.cpp:616
Breakpoint 4 at 0x7ff2a67d48: file widget/PuppetWidget.cpp, line 616.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/bin/harbour-webview 
[...]
Created LOG for EmbedLiteLayerManager

Thread 7 "GeckoWorkerThre" hit Breakpoint 3, nsBaseWidget::
    CreateCompositorSession (this=this@entry=0x7fc4dad520,
    aWidth=aWidth@entry=1080, aHeight=aHeight@entry=2520,
    aOptionsOut=aOptionsOut@entry=0x7fd7da7770)
    at widget/nsBaseWidget.cpp:1364
1364        options.SetInitiallyPaused(CompositorInitiallyPaused());
(gdb) n
43      ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/layers/
    CompositorOptions.h: No such file or directory.
(gdb) 
1369          lm = new WebRenderLayerManager(this);
(gdb) p options
$4 = {mUseAPZ = true, mUseWebRender = true, mUseSoftwareWebRender = true,
    mAllowSoftwareWebRenderD3D11 = false, mAllowSoftwareWebRenderOGL = false, 
  mUseAdvancedLayers = false, mUseWebGPU = false, mInitiallyPaused = false}
(gdb) 
The options structure is really clean and it's helpful to be able to see all of the contents like this.

So we now know that the Web Render version of the layer manager is being created in nsBaseWidget::CreateCompositorSession(). There are two questions that immediately spring to mind: first, if the Client version of the layer manager were being created at this point, would it fix things? Second, is it possible to run with the Web Render layer manager instead?

I also want to know exactly what inputs are being used to decide which type of layer manager to use. Stepping through the nsBaseWidget::CreateCompositorSession() is likely to help with this, so let's give that a go.
(gdb) delete break
Delete all breakpoints? (y or n) y
(gdb) break nsBaseWidget::CreateCompositorSession
Breakpoint 5 at 0x7ff2a578f8: file widget/nsBaseWidget.cpp, line 1308.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/bin/harbour-webview 
[...]

Thread 7 "GeckoWorkerThre" hit Breakpoint 5, nsBaseWidget::
    CreateCompositorSession (this=this@entry=0x7fc4db8a30,
    aWidth=aWidth@entry=1080, aHeight=aHeight@entry=2520,
    aOptionsOut=aOptionsOut@entry=0x7fd7da7770)
    at widget/nsBaseWidget.cpp:1308
1308        int aWidth, int aHeight, CompositorOptions* aOptionsOut) {
(gdb) n
1312        CreateCompositorVsyncDispatcher();
(gdb) n
1314        gfx::GPUProcessManager* gpu = gfx::GPUProcessManager::Get();
(gdb) n
1318        gpu->EnsureGPUReady();
(gdb) n
1324        bool supportsAcceleration = WidgetTypeSupportsAcceleration();
(gdb) n
1327        if (supportsAcceleration ||
(gdb) n
1329          enableWR = gfx::gfxVars::UseWebRender();
(gdb) n
195     ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/gfx/gfxVars.h:
    No such file or directory.
(gdb) n
1338        bool enableAPZ = UseAPZ();
(gdb) n
1339        CompositorOptions options(enableAPZ, enableWR, enableSWWR);
(gdb) p supportsAcceleration
$8 = <optimized out>
(gdb) p enableAPZ
$5 = true
(gdb) p enableWR
$6 = true
(gdb) p enableSWWR
$7 = true
(gdb) n
1357        options.SetUseWebGPU(StaticPrefs::dom_webgpu_enabled());
(gdb) p StaticPrefs::dom_webgpu_enabled()
$9 = false
(gdb) n
mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, void>::operator bool
    (this=<optimized out>)
    at ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/layers/
    CompositorOptions.h:67
67      ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/layers/
    CompositorOptions.h: No such file or directory.
(gdb) n
nsBaseWidget::CreateCompositorSession (this=this@entry=0x7fc4db8a30,
    aWidth=aWidth@entry=1080, aHeight=aHeight@entry=2520, 
    aOptionsOut=aOptionsOut@entry=0x7fd7da7770)
    at widget/nsBaseWidget.cpp:1364
1364        options.SetInitiallyPaused(CompositorInitiallyPaused());
(gdb) n
43      ${PROJECT}/obj-build-mer-qt-xr/dist/include/mozilla/layers/
    CompositorOptions.h: No such file or directory.
(gdb) n
1369          lm = new WebRenderLayerManager(this);
(gdb) 
That gives us some things to work with, but to actually dig into what this all means will have to wait until the morning.

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