Closed Bug 1416533 Opened 7 years ago Closed 7 years ago

Try to composite 30fps video as 60fps

Categories

(Core :: Graphics: WebRender, enhancement, P1)

enhancement

Tracking

()

RESOLVED FIXED
mozilla59
Tracking Status
firefox57 --- unaffected
firefox58 --- unaffected
firefox59 --- fixed

People

(Reporter: sotaro, Assigned: sotaro)

References

Details

(Whiteboard: [wr-mvp] [gfx-noted])

Attachments

(1 file, 7 obsolete files)

WebRenderBridgeParent tries to composite 30fps video as 60fps. Non-webrender cases composite it as 30fps.

The following part check invalidation and if there is no invalid region and skip composite if there is no invalid region.
https://dxr.mozilla.org/mozilla-central/source/gfx/layers/mlgpu/LayerManagerMLGPU.cpp#313
https://dxr.mozilla.org/mozilla-central/source/gfx/layers/composite/LayerManagerComposite.cpp#523
(In reply to Sotaro Ikeda [:sotaro] from comment #0)
> The following part check invalidation and if there is no invalid region and
> skip composite if there is no invalid region.
> https://dxr.mozilla.org/mozilla-central/source/gfx/layers/mlgpu/
> LayerManagerMLGPU.cpp#313
> https://dxr.mozilla.org/mozilla-central/source/gfx/layers/composite/
> LayerManagerComposite.cpp#523

non-WebRender case always do drawing during getting snapshot.
Whiteboard: [wr-mvp] [triage]
Whiteboard: [wr-mvp] [triage] → [wr-mvp]
Whiteboard: [wr-mvp] → [wr-mvp] [gfx-noted]
Assignee: nobody → sotaro.ikeda.g
Status: NEW → ASSIGNED
Priority: P2 → P1
WebRenderBridgeParent::CompositeToTarget() always tries to call mApi->GenerateFrame(). But we could skip to call the GenerateFrame() if there is no display list update, no animation, no apz update, no video update.
If there is an async pipeline for video, WebRenderBridgeParent::CompositeToTarget() is called regularly to check if there is an update to display list or to wr::ResourceUpdate of the video. If there is no update related to the video and no another update, we could skip to call mApi->GenerateFrame().
Attachment #8932298 - Attachment is obsolete: true
Attachment #8932299 - Attachment is obsolete: true
Attachment #8932300 - Flags: review?(bugmail)
Comment on attachment 8932300 [details] [diff] [review]
patch - Skip to generate frame if there is no update

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

Some comments and questions below

::: gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ +272,5 @@
>                               !!pipeline->mCurrentTexture;
>  
> +    // Request to generate frame if there is an update.
> +    if (updateDisplayList || !op.isNothing()) {
> +      SetWillGenerateFrame();

Somebody else should review this part, I don't know if this is correct

::: gfx/layers/wr/AsyncImagePipelineManager.h
@@ +179,5 @@
>  
>    nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
>    nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
>    uint32_t mAsyncImageEpoch;
> +  bool mWillGenerateFrame;

Is this variable threadsafe? It seems to me that SetWillGenerateFrame and GetAndResetWillGenerateFrame might be called from different threads. If not please add thread assertions in those functions.

And actually it seems weird to be putting this flag in AsyncImagePipelineManager instead of just keeping it in WebRenderBridgeParent; most of the rest of the logic regarding this is in that class. What happens if WebRenderBridgeParent::UpdateWebRender is called and a new AsyncImagePipelineManager is installed? Shouldn't we set this flag back to true on the new AsyncImagePipelineManager? Again it seems like keeping the flag in WebRenderBridgeParent would be better because it wouldn't have this problem.

::: gfx/layers/wr/WebRenderBridgeParent.cpp
@@ +1197,5 @@
>    mAsyncImageManager->ApplyAsyncImages();
>  
> +  if (!mAsyncImageManager->GetCompositeUntilTime().IsNull()) {
> +    // Will check if we will generate frame.
> +    mCompositorScheduler->ScheduleComposition();

This comment doesn't make sense to me. If I understand correctly, this code is scheduling another composition because there might be another frame that we want to generate after this one. This call to ScheduleComposition() will trigger another call to this CompositeToTarget function, which is the thing that will check if we actually want to generate the frame or not. If this is correct please expand the comment a little to explain this in more detail.

@@ +1308,4 @@
>  {
>    if (mCompositorScheduler) {
>      mCompositorScheduler->ScheduleComposition();
> +    mAsyncImageManager->SetWillGenerateFrame();

It would be better if the SetWillGenerateFrame call happens first, followed by the ScheduleComposition call

::: gfx/layers/wr/WebRenderImageHost.cpp
@@ +71,5 @@
>    newImages.Clear();
>  
> +  if (mWrBridge && mWrBridge->CompositorScheduler() && GetAsyncRef()) {
> +    // Will check if we will generate frame.
> +    mWrBridge->CompositorScheduler()->ScheduleComposition();

Somebody else should review this, I don't know what this code does
(In reply to Kartikaya Gupta (email:kats@mozilla.com) from comment #7)
> 
> ::: gfx/layers/wr/AsyncImagePipelineManager.h
> @@ +179,5 @@
> >  
> >    nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
> >    nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
> >    uint32_t mAsyncImageEpoch;
> > +  bool mWillGenerateFrame;
> 
> Is this variable threadsafe? It seems to me that SetWillGenerateFrame and
> GetAndResetWillGenerateFrame might be called from different threads. If not
> please add thread assertions in those functions.

mWillGenerateFrame is accessed only on Compositor thread I will add ASSERT here.

> And actually it seems weird to be putting this flag in
> AsyncImagePipelineManager instead of just keeping it in
> WebRenderBridgeParent; most of the rest of the logic regarding this is in
> that class.

It is because mWillGenerateFrame could be handled only by root WebRenderBridgeParent. Non-root WebRenderBridgeParent needs to send the info to root WebRenderBridgeParent. But Non-root WebRenderBridgeParent does not have ref of root WebRenderBridgeParent.

AsyncImagePipelineManager is shared among all WebRenderBridgeParents in a same Window. Therefore I choose AsyncImagePipelineManager as store of mWillGenerateFrame flag.


> What happens if WebRenderBridgeParent::UpdateWebRender is called
> and a new AsyncImagePipelineManager is installed?

It could happen only on non-root WebRenderBridgeParent. Old Window just trigger a GenerateFrame. New Window will trigger GenerateFrame when new display list arrives from client.

> Shouldn't we set this flag back to true on the new AsyncImagePipelineManager? Again it seems like
> keeping the flag in WebRenderBridgeParent would be better because it
> wouldn't have this problem.

I could not find a reason to do it. In this case, non-root WebRenderBridgeParent needs to own ref of root WebRenderBridgeParent. I do not find a necessity to do it now. We already use AsyncImagePipelineManager as a shared data store place for WebRenderBridgeParents in a same window.


> 
> ::: gfx/layers/wr/WebRenderBridgeParent.cpp
> @@ +1197,5 @@
> >    mAsyncImageManager->ApplyAsyncImages();
> >  
> > +  if (!mAsyncImageManager->GetCompositeUntilTime().IsNull()) {
> > +    // Will check if we will generate frame.
> > +    mCompositorScheduler->ScheduleComposition();
> 
> This comment doesn't make sense to me. If I understand correctly, this code
> is scheduling another composition because there might be another frame that
> we want to generate after this one. This call to ScheduleComposition() will
> trigger another call to this CompositeToTarget function, which is the thing
> that will check if we actually want to generate the frame or not. If this is
> correct please expand the comment a little to explain this in more detail.

Yes it is correct. I' will update the comment.

> 
> @@ +1308,4 @@
> >  {
> >    if (mCompositorScheduler) {
> >      mCompositorScheduler->ScheduleComposition();
> > +    mAsyncImageManager->SetWillGenerateFrame();
> 
> It would be better if the SetWillGenerateFrame call happens first, followed
> by the ScheduleComposition call
> 

I will update it.
Attachment #8932300 - Attachment is obsolete: true
Attachment #8932300 - Flags: review?(bugmail)
Attachment #8932705 - Flags: review?(bugmail)
Attachment #8932705 - Flags: review?(nical.bugzilla)
Attachment #8932705 - Attachment is obsolete: true
Attachment #8932705 - Flags: review?(nical.bugzilla)
Attachment #8932705 - Flags: review?(bugmail)
(In reply to Sotaro Ikeda [:sotaro] from comment #8)
> > What happens if WebRenderBridgeParent::UpdateWebRender is called
> > and a new AsyncImagePipelineManager is installed?
> 
> It could happen only on non-root WebRenderBridgeParent. Old Window just
> trigger a GenerateFrame.

The frame does not have resources related to the non-root WebRenderBridgeParent. They are already removed before generating frame.
Attachment #8932706 - Flags: review?(nical.bugzilla)
Attachment #8932706 - Flags: review?(bugmail)
Comment on attachment 8932706 [details] [diff] [review]
patch - Skip to generate frame if there is no update

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

::: gfx/layers/wr/WebRenderBridgeParent.cpp
@@ +1197,5 @@
>    mAsyncImageManager->ApplyAsyncImages();
>  
> +  if (!mAsyncImageManager->GetCompositeUntilTime().IsNull()) {
> +    // Trigger another CompositeToTarget() call because there might be another
> +    // frame that we want to generate after this one. 

nit: trailing whitespace
Attachment #8932706 - Flags: review?(bugmail) → review+
Applied the comment.
Attachment #8932706 - Attachment is obsolete: true
Attachment #8932706 - Flags: review?(nical.bugzilla)
Attachment #8933149 - Flags: review?(nical.bugzilla)
Comment on attachment 8933149 [details] [diff] [review]
patch - Skip to generate frame if there is no update

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

::: gfx/layers/wr/WebRenderBridgeParent.h
@@ +172,5 @@
>    const WebRenderScrollData& GetScrollData() const;
>  
>    void FlushRendering(bool aIsSync);
>  
> +  void ScheduleGenerateFrame();

I think that the difference (if I understand correctly) between SchedulGenerateFrame (will trigger rendering no matter what), and ScheduleComposition (will schedule something that will generate the frame if need be but not necessarily) should be documented here,  because it's not trivial to choose between the two if you haven't read what this bug is about.
Attachment #8933149 - Flags: review?(nical.bugzilla) → review+
I am going to add a comment to ScheduleGenerateFrame().
Added comment.
Attachment #8933149 - Attachment is obsolete: true
Attachment #8933256 - Flags: review+
Attachment #8933256 - Attachment is obsolete: true
Attachment #8933257 - Flags: review+
Pushed by sikeda@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/34e36fdc6b3e
Skip to generate frame if there is no update r=nical,kats
https://hg.mozilla.org/mozilla-central/rev/34e36fdc6b3e
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla59
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: