Closed Bug 1005322 Opened 10 years ago Closed 10 years ago

Implement "invalidate" hook for HwcComposer2D.

Categories

(Core Graveyard :: Widget: Gonk, defect)

ARM
Gonk (Firefox OS)
defect
Not set
normal

Tracking

(blocking-b2g:2.1+, firefox33 wontfix, firefox34 fixed, firefox35 fixed, b2g-v2.1 fixed, b2g-v2.2 fixed)

RESOLVED FIXED
mozilla35
blocking-b2g 2.1+
Tracking Status
firefox33 --- wontfix
firefox34 --- fixed
firefox35 --- fixed
b2g-v2.1 --- fixed
b2g-v2.2 --- fixed

People

(Reporter: sushilchauhan, Assigned: sushilchauhan)

References

Details

Attachments

(3 files, 5 obsolete files)

I am planning to implement "invalidate" hook for HwcComposer2D. The idea is to have mechanism to queue a Render request from HwcComposer2D on current mRoot / composition layer tree, similar to LayerManagerComposite::EndTransaction() call.

Here is reference from Android:
- https://android.googlesource.com/platform/frameworks/native/+/kitkat-dev/services/surfaceflinger/DisplayHardware/HWComposer.cpp#281
- https://android.googlesource.com/platform/frameworks/native/+/kitkat-dev/services/surfaceflinger/DisplayHardware/HWComposer.cpp#261
- https://android.googlesource.com/platform/frameworks/native/+/kitkat-dev/services/surfaceflinger/DisplayHardware/HWComposer.cpp#138
I need your inputs on this.
Flags: needinfo?(ncameron)
Flags: needinfo?(mwu)
Flags: needinfo?(matt.woodrow)
Is it ok, to get hold of Layer Manager object and just call EndTransaction() on it ?
Can you please explain what problem you're trying to solve with this?
Flags: needinfo?(matt.woodrow)
(In reply to Matt Woodrow (:mattwoodrow) from comment #3)
> Can you please explain what problem you're trying to solve with this?

It is needed for an optimization where HAL initiates an invalidate once via mCBContext->procs.invalidate hook. The aim is to queue a Render request from HAL with the existing layer tree. Meanwhile, if a new update comes from framework via normal LayerManagerComposite::EndTransaction() path, then that will be preferred. I think we can start supporting normal hwc hooks like invalidate, vsync and hotplug.
(In reply to Sushil from comment #4)
> I think we can start supporting normal hwc hooks like
> invalidate, vsync and hotplug.

Bug 987527 implements some of those hooks - maybe you can build on top of that?
Flags: needinfo?(mwu)
Flags: needinfo?(ncameron)
Assignee: nobody → sushilchauhan
Depends on: 987527
(In reply to Michael Wu [:mwu] from comment #5)
> Bug 987527 implements some of those hooks - maybe you can build on top of
> that?

Bug 987527 implements Vsync hook. I will implement "invalidate" hook in this bug. Currently, looking into Layer Manager code to find a simple way of doing it.
Attaching the prototype patch to be discussed.
Hi MWu, Matt and Sotaro,

I need your inputs. Patch in Comment 7 is a prototype of what I am trying to do. In static display use case, I want to trigger a composition cycle from HwcComposer2D::Invalidate(). Current patch is not correct because HwcComposer2D::Invalidate() gets called on the "invalidator" thread (run from HAL) but I want to execute this new Composition cycle (BeginTransaction & EndEmptyTransaction) on the original Compositor thread. To achieve this, I need to signal the Compositor thread from Invalidate(). Basically, we need to implement it as similar to [1]. Hence, I need your inputs / few pointers here. We need HWC invalidate() hook to support a Power optimization in HAL.

I believe [2] should be the appropriate point to trigger on Compositor thread to run a Composition cycle.
Also I noticed with current patch that the layer tree with root as "mRoot" has changed when TryRender() gets called in the HwcComposer2D::Invalidate() call. For ex: In paused Video use case, layer tree of the last static frame had Color, Thebes and Image layer. But I could see only a Color layer, via Invalidate call. So it seems the layer tree of mRoot has changed after last Composition phase. Are we destroying layer tree after each Composition Phase? If Yes, then I need to look into it because I am relying on mRoot to preserve the last layer tree since no painting has happened after last frame update from framework (as it is static use case).

[1]: https://android.googlesource.com/platform/frameworks/native/+/kitkat-dev/services/surfaceflinger/DisplayHardware/HWComposer.cpp#281

[2]: http://mxr.mozilla.org/mozilla-central/source/gfx/layers/ipc/CompositorParent.cpp#461
Flags: needinfo?(sotaro.ikeda.g)
Flags: needinfo?(mwu)
Flags: needinfo?(matt.woodrow)
Flags: needinfo?(sotaro.ikeda.g)
On android, the function call sequence like the following.

->HWComposer::hook_invalidate() //hw composer hal's "invalidator" thread
 ->HWComposer::invalidate()
  ->SurfaceFlinger::repaintEverything()
     // Trigger SurfaceFlinger's composition
(In reply to Sushil from comment #8)
> Also I noticed with current patch that the layer tree with root as "mRoot"
> has changed when TryRender() gets called in the HwcComposer2D::Invalidate()
> call. For ex: In paused Video use case, layer tree of the last static frame
> had Color, Thebes and Image layer. But I could see only a Color layer, via
> Invalidate call. So it seems the layer tree of mRoot has changed after last
> Composition phase. Are we destroying layer tree after each Composition
> Phase?

LayerTree is not destroyed for each rendering. It is updated by requests from layout(DisplayList), though it is very dynamic compared to android.
LayerManager and Compositor APIs are not thread safe, they basically need to be called on compositor thread.  CompositorParent::ScheduleRenderOnCompositorThread() is a function to trigger render from other thread. It might be used for it.

http://dxr.mozilla.org/mozilla-central/source/gfx/layers/ipc/CompositorParent.cpp#435
Thanks Sotaro.

CompositorParent::ScheduleRenderOnCompositorThread() worked for me. I will upload the patch for review, after some more testing.
Flags: needinfo?(mwu)
Flags: needinfo?(matt.woodrow)
This patch implements HWC invalidate hook. Please review. HWC invalidate is required to support a Power optimization in HAL for static display use cases.
Attachment #8488713 - Attachment is obsolete: true
Attachment #8491075 - Flags: review?(sotaro.ikeda.g)
Attachment #8491075 - Flags: review?(mwu)
Boris,

The patch in Comment 13 implements HWC invalidate hook but it's enabling is blocked by check at [1] which was landed in Bugzilla 987527. I believe registerProcs() is required to register all HWC hooks. It should not be blocked by Vsync check at [1]. So we should remove check at [1], and instead add the "Vsync disable check" at [2] like this: 

-    return true;
+
+    if (!gfxPrefs::FrameUniformityHWVsyncEnabled()) {
+        device->eventControl(device, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, false);
+        mHasHWVsync = false;
+    }
+
+    return mHasHWVsync;

Since it is not related to HWC invalidate implementation. So I wanted this to land in a separate patch. Please let me know, if you want me to add this code in current patch.

[1]: http://mxr.mozilla.org/mozilla-central/source/widget/gonk/HwcComposer2D.cpp#199
[2]: http://mxr.mozilla.org/mozilla-central/source/widget/gonk/HwcComposer2D.cpp#214
Flags: needinfo?(boris.chiou)
Hmm, the way that this patch grabs a LayerManager doesn't seem ideal. Instead, can we explicitly pass the LayerManager to HwcComposer2D in nsWindow.cpp? nsWindow.cpp would also be able to unset it when it's getting destroyed.
(In reply to Sushil from comment #14)
> Boris,
> 
> The patch in Comment 13 implements HWC invalidate hook but it's enabling is
> blocked by check at [1] which was landed in Bugzilla 987527. I believe
> registerProcs() is required to register all HWC hooks. It should not be
> blocked by Vsync check at [1]. So we should remove check at [1], and instead
> add the "Vsync disable check" at [2] like this: 
> 
> -    return true;
> +
> +    if (!gfxPrefs::FrameUniformityHWVsyncEnabled()) {
> +        device->eventControl(device, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC,
> false);
> +        mHasHWVsync = false;
> +    }
> +
> +    return mHasHWVsync;
> 
> Since it is not related to HWC invalidate implementation. So I wanted this
> to land in a separate patch. Please let me know, if you want me to add this
> code in current patch.
> 

Using a separate patch is OK to me. Thanks for fixing this problem.

> [1]:
> http://mxr.mozilla.org/mozilla-central/source/widget/gonk/HwcComposer2D.
> cpp#199
> [2]:
> http://mxr.mozilla.org/mozilla-central/source/widget/gonk/HwcComposer2D.
> cpp#214
Flags: needinfo?(boris.chiou)
(In reply to Michael Wu [:mwu] from comment #15)
> Hmm, the way that this patch grabs a LayerManager doesn't seem ideal.
> Instead, can we explicitly pass the LayerManager to HwcComposer2D in
> nsWindow.cpp? nsWindow.cpp would also be able to unset it when it's getting
> destroyed.

MWu,

Yes, I also agree because current patch grabs LayerManagerComposite* in Invalidate(), which is not ideal since Layer Manager does not change for each Root layer (layer tree). But we cannot set it from nsWindow Constructor because it is too early in pipeline. HwcComposer2D and LayerManagerComposite are not initialized by that time. Here is the flow during boot-up:

E/        (  199): GonkDisplayJB::GonkDisplayJB()
E/Gonk    (  199): nsWindow::nsWindow()
E/HWComposer(  199): HwcComposer2D::HwcComposer2D()
E/lmComposite(  199): LayerManagerComposite::LayerManagerComposite()
E/lmComposite(  199): LayerManagerComposite::Initialize()
E/glContext(  199): GLContextEGL::GLContextEGL()
E/glContext(  199): GLContextEGL::GLContextEGL ... Call mHwc->Init
E/HWComposer(  199): HwcComposer2D::Init()
E/lmComposite(  199): LayerManagerComposite::Render()

I would suggest, we can set it from LayerManagerComposite::Initialize(). OR let me know, if you were thinking of setting it from another place in nsWindow.cpp ?
Flags: needinfo?(mwu)
I was thinking of setting it up in GetLayerManager where a lot of the layer manager and compositing code is setup. Dunno if you can get the right things there, but it seems like it might work.
Flags: needinfo?(mwu)
I feel that the function calls from HwcComposer2D::Invalidate() to CompositorParent::ScheduleRenderOnCompositorThread() is a bit long. It might becomes simpler when HwcComposer2D directly calls the ScheduleRenderOnCompositorThread().

can't we register CompositorParent to HwcComposer2D in nsWindow::GetLayerManager() after calling CreateCompositor()?
Attaching patch as per Comment 18.
Attached file delayed_render.txt (obsolete) (deleted) —
Attaching delayed render logs with patch of Comment 20.
(In reply to Michael Wu [:mwu] from comment #18)
> I was thinking of setting it up in GetLayerManager where a lot of the layer
> manager and compositing code is setup. Dunno if you can get the right things
> there, but it seems like it might work.

Hi MWu,

There was no issue with my last patch. But when I tried with this approach (patch in Comment 20). I noticed that there is delay of ~ 18 sec in scheduling the Render on Compositor thread. But Invalidate() call finishes instantly (it has no issues). The delay occurs only in the scheduling. Please check logs in Comment 21, let me know if I have missed something. This is during static display use case.
Flags: needinfo?(mwu)
(In reply to Sotaro Ikeda [:sotaro] from comment #19)
> can't we register CompositorParent to HwcComposer2D in
> nsWindow::GetLayerManager() after calling CreateCompositor()?

Sotaro,

Can you please provide more details / few pointers? I am not much familiar with CompositorParent class in Gecko. As per my testing, HwcComposer2D::Invalidate() call does not take any time to finish.
Flags: needinfo?(sotaro.ikeda.g)
Added more logs for Comment 22, CompositorParent::ScheduleComposition() call is getting delayed.
Here are logs:

01-01 05:45:19.389   221   678 E HWComposer: HWC: HookInvalidate
01-01 05:45:19.389   221   678 E HWComposer: HwcComposer2D::Invalidate E
01-01 05:45:19.389   221   678 E lmComposite: LayerManagerComposite::ScheduleComposition E
01-01 05:45:19.389   221   678 E lmComposite: LayerManagerComposite::ScheduleComposition X
01-01 05:45:19.389   221   678 E HWComposer: HwcComposer2D::Invalidate X
....
01-01 05:46:00.409   221  1009 E CompositorParent: CompositorParent::ScheduleComposition
01-01 05:46:00.409   221  1009 E CompositorParent: CompositorParent::CompositeToTarget
01-01 05:46:00.409   221  1009 E CompositorParent: CompositeToTarget: lm->BeginTransaction
01-01 05:46:00.409   221  1009 E CompositorParent: CompositeToTarget: lm->EndEmptyTransaction
01-01 05:46:00.409   221  1009 E lmComposite: LayerManagerComposite::Render
I found out the cause for issue in Comment 22. In LayerManagerComposite::ScheduleComposition(), "mCompositor" is NULL but if I check it at [1] in previous/next Render() call, it is not NULL. It means we have a stale LayerManager (hence LayerManagerComposite) object in HwcComposer2D::Invalidate(). Hence, nsWindow::ScheduleRender() was never called. That next delayed Render() was a normal framework update.

MWu,
I think the previous patch (attachment 8491075 [details] [diff] [review]) was fine. We are just caching mRoot* of every frame and whenever Invalidate() happens, we grab the updated LayerManager* with "mRoot->Manager()" api. If you have any other suggestions, please let me know.

[1]: http://mxr.mozilla.org/mozilla-central/source/gfx/layers/composite/LayerManagerComposite.cpp#603
Flags: needinfo?(sotaro.ikeda.g)
(In reply to Sushil from comment #23)
> (In reply to Sotaro Ikeda [:sotaro] from comment #19)
> > can't we register CompositorParent to HwcComposer2D in
> > nsWindow::GetLayerManager() after calling CreateCompositor()?
> 
> Sotaro,
> 
> Can you please provide more details / few pointers? I am not much familiar
> with CompositorParent class in Gecko. As per my testing,
> HwcComposer2D::Invalidate() call does not take any time to finish.

I think a code like attachment 8493110 [details] [diff] [review] is simpler. Can you confirm if the patch work?
(In reply to Sushil from comment #24)
> Added more logs for Comment 22, CompositorParent::ScheduleComposition() call
> is getting delayed.
> Here are logs:

Compositor thread might be busy for other tasks. The compositor thread does LayerTransaction, APZ, Composition.
(In reply to Sotaro Ikeda [:sotaro] from comment #28)
> (In reply to Sushil from comment #24)
> > Added more logs for Comment 22, CompositorParent::ScheduleComposition() call
> > is getting delayed.
> > Here are logs:
> 
> Compositor thread might be busy for other tasks. The compositor thread does
> LayerTransaction, APZ, Composition.

No, I mentioned the root cause in Comment 25. So, nsWindow::ScheduleRender() was never being called with attachment 8492382 [details] [diff] [review]. The next Render() was a normal framework update (time update on Status Bar).
Sushi, how can I test the patches on flame device? I am not sure how to intentionally trigger HookInvalidate() from hal.
Flags: needinfo?(sushilchauhan)
(In reply to Sotaro Ikeda [:sotaro] from comment #27)
> 
> I think a code like attachment 8493110 [details] [diff] [review] is simpler.
> Can you confirm if the patch work?

Thanks. I will check with this patch and let you know.
Flags: needinfo?(sushilchauhan)
(In reply to Sotaro Ikeda [:sotaro] from comment #27)
> 
> I think a code like attachment 8493110 [details] [diff] [review] is simpler.
> Can you confirm if the patch work?

Sotaro,

Yes, the patch works fine and it is simpler than mine. Do you want to upload this patch or you want me to upload ?

Regarding Comment 30, our optimization is only for H/W Overlay devices, so HookInvalidate() will not be triggered on Flame device. To test, you will also need change in Comment 14 (to register hooks), which we are planning to land in a separate patch (bugzilla).
Flags: needinfo?(mwu) → needinfo?(sotaro.ikeda.g)
Or should we include that change (Comment 14) in current patch? I don't want to create a new Bugzilla. What do you say ?
(In reply to Sushil from comment #33)
> Or should we include that change (Comment 14) in current patch? I don't want
> to create a new Bugzilla. What do you say ?

Can you update a new patch that have Comment 14? It makes things simpler :-)
Flags: needinfo?(sotaro.ikeda.g)
Sotaro, I have attached the patch for Comment 14.

Registration of HWC hooks should not be blocked by gfx preference for enabling H/W Vsync.
Attachment #8492382 - Attachment is obsolete: true
Attachment #8492384 - Attachment is obsolete: true
I have uploaded only Comment 14 patch. Or did you want me to upload the final consolidated patch ?
Flags: needinfo?(sotaro.ikeda.g)
I am going to update attachment 8493110 [details] [diff] [review]. It has some parts that seems better to be updated.
Flags: needinfo?(sotaro.ikeda.g)
Attached patch patch - Hold CompositorParent at HwcComposer2D (obsolete) (deleted) — Splinter Review
Fix thread safety.
Attachment #8493110 - Attachment is obsolete: true
It might be better the patches reviewed individually.
Attachment #8493758 - Flags: review?(sushilchauhan)
Attachment #8493758 - Flags: review?(mwu)
This approach looks good to me.
Comment on attachment 8493758 [details] [diff] [review]
patch - Hold CompositorParent at HwcComposer2D

Review of attachment 8493758 [details] [diff] [review]:
-----------------------------------------------------------------

::: widget/gonk/HwcComposer2D.h
@@ +18,5 @@
>  #define mozilla_HwcComposer2D
>  
>  #include "Composer2D.h"
>  #include "Layers.h"
> +#include "mozilla/Mutex.h" 

trailing whitespace

::: widget/gonk/nsWindow.cpp
@@ +604,5 @@
>      return nullptr;
>  }
>  
> +void
> +nsWindow::DestroyCompositor()

I think we can avoid implementing our own DestroyCompositor() entirely - DestroyCompositor is only called on the destruction of this window and if CreateCompositor fails. If CreateCompositor fails, we don't call SetCompositorParent. So we only need to SetCompositorParent(nullptr) in ~nsWindow().
Attachment #8491075 - Flags: review?(sotaro.ikeda.g)
Attachment #8491075 - Flags: review?(mwu)
Comment on attachment 8493758 [details] [diff] [review]
patch - Hold CompositorParent at HwcComposer2D

Review of attachment 8493758 [details] [diff] [review]:
-----------------------------------------------------------------

::: widget/gonk/HwcComposer2D.cpp
@@ +110,5 @@
>      , mPrevRetireFence(Fence::NO_FENCE)
>      , mPrevDisplayFence(Fence::NO_FENCE)
>  #endif
>      , mPrepared(false)
>      , mHasHWVsync(false)

No need to initialize "mCompositorParent" here ?
Depends on: 1071704
Raised new Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1071704 for Comment 16.
(In reply to Sushil from comment #42)
> Comment on attachment 8493758 [details] [diff] [review]
> patch - Hold CompositorParent at HwcComposer2D
> 
> Review of attachment 8493758 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> ::: widget/gonk/HwcComposer2D.cpp
> @@ +110,5 @@
> >      , mPrevRetireFence(Fence::NO_FENCE)
> >      , mPrevDisplayFence(Fence::NO_FENCE)
> >  #endif
> >      , mPrepared(false)
> >      , mHasHWVsync(false)
> 
> No need to initialize "mCompositorParent" here ?

nsRefPtr initialize the raw pointer to nullptr;
(In reply to Michael Wu [:mwu] from comment #41)
> Comment on attachment 8493758 [details] [diff] [review]
> patch - Hold CompositorParent at HwcComposer2D
> 
> Review of attachment 8493758 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> ::: widget/gonk/HwcComposer2D.h
> @@ +18,5 @@
> >  #define mozilla_HwcComposer2D
> >  
> >  #include "Composer2D.h"
> >  #include "Layers.h"
> > +#include "mozilla/Mutex.h" 
> 
> trailing whitespace
> 
> ::: widget/gonk/nsWindow.cpp
> @@ +604,5 @@
> >      return nullptr;
> >  }
> >  
> > +void
> > +nsWindow::DestroyCompositor()
> 
> I think we can avoid implementing our own DestroyCompositor() entirely -
> DestroyCompositor is only called on the destruction of this window and if
> CreateCompositor fails. If CreateCompositor fails, we don't call
> SetCompositorParent. So we only need to SetCompositorParent(nullptr) in
> ~nsWindow().

Yhea, ~nsWindow() seems enough. I added DestroyCompositor() because, b2g created 3 nsWindow instances. But they are all alive until shutdown.
Apply the comments.
Attachment #8493758 - Attachment is obsolete: true
Attachment #8493758 - Flags: review?(sushilchauhan)
Attachment #8493758 - Flags: review?(mwu)
Attachment #8493914 - Flags: review?(sushilchauhan)
Attachment #8493914 - Flags: review?(mwu)
Comment on attachment 8493914 [details] [diff] [review]
patch - Hold CompositorParent at HwcComposer2D

Review of attachment 8493914 [details] [diff] [review]:
-----------------------------------------------------------------

Looks good, thanks.
Attachment #8493914 - Flags: review?(mwu) → review+
Comment on attachment 8493914 [details] [diff] [review]
patch - Hold CompositorParent at HwcComposer2D

Review of attachment 8493914 [details] [diff] [review]:
-----------------------------------------------------------------

LGTM.
Attachment #8493914 - Flags: review?(sushilchauhan) → review+
(In reply to Sotaro Ikeda [:sotaro] from comment #49)
> https://tbpl.mozilla.org/?tree=Try&rev=bcc450139e96

Hmm, all builds are failed by wired errors.
https://hg.mozilla.org/mozilla-central/rev/03b1abc4f5e7
Status: NEW → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla35
[Blocking Requested - why for this release]: HWC invalidate hook is required for an optimization in HAL.
blocking-b2g: --- → 2.1?
(In reply to Sushil from comment #54)
> [Blocking Requested - why for this release]: HWC invalidate hook is required
> for an optimization in HAL.

Please seek approval for mozilla-aurora when ready.
blocking-b2g: 2.1? → 2.1+
Comment on attachment 8493914 [details] [diff] [review]
patch - Hold CompositorParent at HwcComposer2D

Approval Request Comment
[Feature/regressing bug #]: Power optimization in static display use cases, which use full/partial HWC Composition path.
[User impact if declined]: No user impact but power numbers will not be optimized.
[Describe test coverage new/current, TBPL]: Basic display sanity test, including Video playback, Camera/Camcorder, UI, etc.
[Risks and why]: No
[String/UUID change made/needed]: No
Attachment #8493914 - Flags: approval-mozilla-aurora?
Attachment #8493914 - Flags: approval-mozilla-aurora? → approval-mozilla-aurora+
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: