Bug 1416533 - Skip to generate frame if there is no update r=nical,kats
This commit is contained in:
@@ -904,8 +904,12 @@ CompositorBridgeParent::ScheduleComposition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mWrBridge) {
|
||||||
|
mWrBridge->ScheduleGenerateFrame();
|
||||||
|
} else {
|
||||||
mCompositorScheduler->ScheduleComposition();
|
mCompositorScheduler->ScheduleComposition();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Go down the composite layer tree, setting properties to match their
|
// Go down the composite layer tree, setting properties to match their
|
||||||
// content-side counterparts.
|
// content-side counterparts.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "CompositableHost.h"
|
#include "CompositableHost.h"
|
||||||
#include "gfxEnv.h"
|
#include "gfxEnv.h"
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
|
#include "mozilla/layers/CompositorThread.h"
|
||||||
#include "mozilla/layers/WebRenderImageHost.h"
|
#include "mozilla/layers/WebRenderImageHost.h"
|
||||||
#include "mozilla/layers/WebRenderTextureHost.h"
|
#include "mozilla/layers/WebRenderTextureHost.h"
|
||||||
#include "mozilla/webrender/WebRenderAPI.h"
|
#include "mozilla/webrender/WebRenderAPI.h"
|
||||||
@@ -30,6 +31,7 @@ AsyncImagePipelineManager::AsyncImagePipelineManager(already_AddRefed<wr::WebRen
|
|||||||
, mIdNamespace(mApi->GetNamespace())
|
, mIdNamespace(mApi->GetNamespace())
|
||||||
, mResourceId(0)
|
, mResourceId(0)
|
||||||
, mAsyncImageEpoch(0)
|
, mAsyncImageEpoch(0)
|
||||||
|
, mWillGenerateFrame(false)
|
||||||
, mDestroyed(false)
|
, mDestroyed(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(AsyncImagePipelineManager);
|
MOZ_COUNT_CTOR(AsyncImagePipelineManager);
|
||||||
@@ -48,6 +50,24 @@ AsyncImagePipelineManager::Destroy()
|
|||||||
mDestroyed = true;
|
mDestroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AsyncImagePipelineManager::SetWillGenerateFrame()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||||
|
|
||||||
|
mWillGenerateFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AsyncImagePipelineManager::GetAndResetWillGenerateFrame()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||||
|
|
||||||
|
bool ret = mWillGenerateFrame;
|
||||||
|
mWillGenerateFrame = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
|
AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
|
||||||
{
|
{
|
||||||
@@ -270,6 +290,11 @@ AsyncImagePipelineManager::ApplyAsyncImages()
|
|||||||
(pipeline->mIsChanged || op == Some(TextureHost::ADD_IMAGE)) &&
|
(pipeline->mIsChanged || op == Some(TextureHost::ADD_IMAGE)) &&
|
||||||
!!pipeline->mCurrentTexture;
|
!!pipeline->mCurrentTexture;
|
||||||
|
|
||||||
|
// Request to generate frame if there is an update.
|
||||||
|
if (updateDisplayList || !op.isNothing()) {
|
||||||
|
SetWillGenerateFrame();
|
||||||
|
}
|
||||||
|
|
||||||
if (!updateDisplayList) {
|
if (!updateDisplayList) {
|
||||||
// We don't need to update the display list, either because we can't or because
|
// We don't need to update the display list, either because we can't or because
|
||||||
// the previous one is still up to date.
|
// the previous one is still up to date.
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ public:
|
|||||||
aNotifications->AppendElements(Move(mImageCompositeNotifications));
|
aNotifications->AppendElements(Move(mImageCompositeNotifications));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetWillGenerateFrame();
|
||||||
|
bool GetAndResetWillGenerateFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint32_t GetNextResourceId() { return ++mResourceId; }
|
uint32_t GetNextResourceId() { return ++mResourceId; }
|
||||||
@@ -168,6 +171,7 @@ private:
|
|||||||
nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
|
nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
|
||||||
nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
|
nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
|
||||||
uint32_t mAsyncImageEpoch;
|
uint32_t mAsyncImageEpoch;
|
||||||
|
bool mWillGenerateFrame;
|
||||||
bool mDestroyed;
|
bool mDestroyed;
|
||||||
|
|
||||||
// Render time for the current composition.
|
// Render time for the current composition.
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
|
|||||||
dlDesc, dl.mData, dl.mLen,
|
dlDesc, dl.mData, dl.mLen,
|
||||||
resources);
|
resources);
|
||||||
|
|
||||||
ScheduleComposition();
|
ScheduleGenerateFrame();
|
||||||
|
|
||||||
if (ShouldParentObserveEpoch()) {
|
if (ShouldParentObserveEpoch()) {
|
||||||
mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
|
mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
|
||||||
@@ -664,7 +664,7 @@ WebRenderBridgeParent::RecvEmptyTransaction(const FocusTarget& aFocusTarget,
|
|||||||
if (!aCommands.IsEmpty()) {
|
if (!aCommands.IsEmpty()) {
|
||||||
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
|
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
|
||||||
ProcessWebRenderParentCommands(aCommands);
|
ProcessWebRenderParentCommands(aCommands);
|
||||||
mCompositorScheduler->ScheduleComposition();
|
ScheduleGenerateFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
mScrollData.SetFocusTarget(aFocusTarget);
|
mScrollData.SetFocusTarget(aFocusTarget);
|
||||||
@@ -940,8 +940,8 @@ WebRenderBridgeParent::RecvClearCachedResources()
|
|||||||
|
|
||||||
// Clear resources
|
// Clear resources
|
||||||
mApi->ClearDisplayList(wr::NewEpoch(GetNextWrEpoch()), mPipelineId);
|
mApi->ClearDisplayList(wr::NewEpoch(GetNextWrEpoch()), mPipelineId);
|
||||||
// Schedule composition to clean up Pipeline
|
// Schedule generate frame to clean up Pipeline
|
||||||
mCompositorScheduler->ScheduleComposition();
|
ScheduleGenerateFrame();
|
||||||
// Remove animations.
|
// Remove animations.
|
||||||
for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
|
for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
|
||||||
mAnimStorage->ClearById(*iter);
|
mAnimStorage->ClearById(*iter);
|
||||||
@@ -998,7 +998,7 @@ WebRenderBridgeParent::RecvForceComposite()
|
|||||||
if (mDestroyed) {
|
if (mDestroyed) {
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
ScheduleComposition();
|
ScheduleGenerateFrame();
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,24 +1189,36 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
|
|||||||
if (!mForceRendering &&
|
if (!mForceRendering &&
|
||||||
wr::RenderThread::Get()->TooManyPendingFrames(mApi->GetId())) {
|
wr::RenderThread::Get()->TooManyPendingFrames(mApi->GetId())) {
|
||||||
// Render thread is busy, try next time.
|
// Render thread is busy, try next time.
|
||||||
ScheduleComposition();
|
mCompositorScheduler->ScheduleComposition();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scheduleComposite = false;
|
|
||||||
nsTArray<wr::WrOpacityProperty> opacityArray;
|
|
||||||
nsTArray<wr::WrTransformProperty> transformArray;
|
|
||||||
|
|
||||||
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
|
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
|
||||||
mAsyncImageManager->ApplyAsyncImages();
|
mAsyncImageManager->ApplyAsyncImages();
|
||||||
|
|
||||||
|
if (!mAsyncImageManager->GetCompositeUntilTime().IsNull()) {
|
||||||
|
// Trigger another CompositeToTarget() call because there might be another
|
||||||
|
// frame that we want to generate after this one.
|
||||||
|
// It will check if we actually want to generate the frame or not.
|
||||||
|
mCompositorScheduler->ScheduleComposition();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mAsyncImageManager->GetAndResetWillGenerateFrame() &&
|
||||||
|
!mForceRendering) {
|
||||||
|
// Could skip generating frame now.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<wr::WrOpacityProperty> opacityArray;
|
||||||
|
nsTArray<wr::WrTransformProperty> transformArray;
|
||||||
|
|
||||||
SampleAnimations(opacityArray, transformArray);
|
SampleAnimations(opacityArray, transformArray);
|
||||||
if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
|
if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
|
||||||
scheduleComposite = true;
|
ScheduleGenerateFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PushAPZStateToWR(transformArray)) {
|
if (PushAPZStateToWR(transformArray)) {
|
||||||
scheduleComposite = true;
|
ScheduleGenerateFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId());
|
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId());
|
||||||
@@ -1221,14 +1233,6 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
|
|||||||
} else {
|
} else {
|
||||||
mApi->GenerateFrame();
|
mApi->GenerateFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mAsyncImageManager->GetCompositeUntilTime().IsNull()) {
|
|
||||||
scheduleComposite = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scheduleComposite) {
|
|
||||||
ScheduleComposition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1302,9 +1306,10 @@ WebRenderBridgeParent::GetLayersId() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebRenderBridgeParent::ScheduleComposition()
|
WebRenderBridgeParent::ScheduleGenerateFrame()
|
||||||
{
|
{
|
||||||
if (mCompositorScheduler) {
|
if (mCompositorScheduler) {
|
||||||
|
mAsyncImageManager->SetWillGenerateFrame();
|
||||||
mCompositorScheduler->ScheduleComposition();
|
mCompositorScheduler->ScheduleComposition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1368,8 +1373,8 @@ WebRenderBridgeParent::ClearResources()
|
|||||||
|
|
||||||
uint32_t wrEpoch = GetNextWrEpoch();
|
uint32_t wrEpoch = GetNextWrEpoch();
|
||||||
mApi->ClearDisplayList(wr::NewEpoch(wrEpoch), mPipelineId);
|
mApi->ClearDisplayList(wr::NewEpoch(wrEpoch), mPipelineId);
|
||||||
// Schedule composition to clean up Pipeline
|
// Schedule generate frame to clean up Pipeline
|
||||||
mCompositorScheduler->ScheduleComposition();
|
ScheduleGenerateFrame();
|
||||||
// WrFontKeys and WrImageKeys are deleted during WebRenderAPI destruction.
|
// WrFontKeys and WrImageKeys are deleted during WebRenderAPI destruction.
|
||||||
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
|
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
|
||||||
iter.Data()->ClearWrBridge();
|
iter.Data()->ClearWrBridge();
|
||||||
|
|||||||
@@ -173,7 +173,18 @@ public:
|
|||||||
|
|
||||||
void FlushRendering(bool aIsSync);
|
void FlushRendering(bool aIsSync);
|
||||||
|
|
||||||
void ScheduleComposition();
|
/**
|
||||||
|
* Schedule generating WebRender frame definitely at next composite timing.
|
||||||
|
*
|
||||||
|
* WebRenderBridgeParent uses composite timing to check if there is an update
|
||||||
|
* to AsyncImagePipelines. If there is no update, WebRenderBridgeParent skips
|
||||||
|
* to generate frame. If we need to generate new frame at next composite timing,
|
||||||
|
* call this method.
|
||||||
|
*
|
||||||
|
* Call CompositorVsyncScheduler::ScheduleComposition() directly, if we just
|
||||||
|
* want to trigger AsyncImagePipelines update checks.
|
||||||
|
*/
|
||||||
|
void ScheduleGenerateFrame();
|
||||||
|
|
||||||
void UpdateWebRender(CompositorVsyncScheduler* aScheduler,
|
void UpdateWebRender(CompositorVsyncScheduler* aScheduler,
|
||||||
wr::WebRenderAPI* aApi,
|
wr::WebRenderAPI* aApi,
|
||||||
|
|||||||
@@ -70,8 +70,9 @@ WebRenderImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
|
|||||||
mImages.SwapElements(newImages);
|
mImages.SwapElements(newImages);
|
||||||
newImages.Clear();
|
newImages.Clear();
|
||||||
|
|
||||||
if (mWrBridge && GetAsyncRef()) {
|
if (mWrBridge && mWrBridge->CompositorScheduler() && GetAsyncRef()) {
|
||||||
mWrBridge->ScheduleComposition();
|
// Will check if we will generate frame.
|
||||||
|
mWrBridge->CompositorScheduler()->ScheduleComposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video producers generally send replacement images with the same frameID but
|
// Video producers generally send replacement images with the same frameID but
|
||||||
|
|||||||
Reference in New Issue
Block a user