Bug 1416533 - Skip to generate frame if there is no update r=nical,kats

This commit is contained in:
sotaro 2017-11-30 21:38:47 +09:00
Родитель 5988aed34a
Коммит 78b2129696
6 изменённых файлов: 77 добавлений и 27 удалений

Просмотреть файл

@ -904,7 +904,11 @@ CompositorBridgeParent::ScheduleComposition()
return;
}
mCompositorScheduler->ScheduleComposition();
if (mWrBridge) {
mWrBridge->ScheduleGenerateFrame();
} else {
mCompositorScheduler->ScheduleComposition();
}
}
// Go down the composite layer tree, setting properties to match their

Просмотреть файл

@ -9,6 +9,7 @@
#include "CompositableHost.h"
#include "gfxEnv.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/WebRenderImageHost.h"
#include "mozilla/layers/WebRenderTextureHost.h"
#include "mozilla/webrender/WebRenderAPI.h"
@ -30,6 +31,7 @@ AsyncImagePipelineManager::AsyncImagePipelineManager(already_AddRefed<wr::WebRen
, mIdNamespace(mApi->GetNamespace())
, mResourceId(0)
, mAsyncImageEpoch(0)
, mWillGenerateFrame(false)
, mDestroyed(false)
{
MOZ_COUNT_CTOR(AsyncImagePipelineManager);
@ -48,6 +50,24 @@ AsyncImagePipelineManager::Destroy()
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
AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
{
@ -270,6 +290,11 @@ AsyncImagePipelineManager::ApplyAsyncImages()
(pipeline->mIsChanged || op == Some(TextureHost::ADD_IMAGE)) &&
!!pipeline->mCurrentTexture;
// Request to generate frame if there is an update.
if (updateDisplayList || !op.isNothing()) {
SetWillGenerateFrame();
}
if (!updateDisplayList) {
// We don't need to update the display list, either because we can't or because
// the previous one is still up to date.

Просмотреть файл

@ -91,6 +91,9 @@ public:
aNotifications->AppendElements(Move(mImageCompositeNotifications));
}
void SetWillGenerateFrame();
bool GetAndResetWillGenerateFrame();
private:
uint32_t GetNextResourceId() { return ++mResourceId; }
@ -168,6 +171,7 @@ private:
nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
uint32_t mAsyncImageEpoch;
bool mWillGenerateFrame;
bool mDestroyed;
// Render time for the current composition.

Просмотреть файл

@ -612,7 +612,7 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
dlDesc, dl.mData, dl.mLen,
resources);
ScheduleComposition();
ScheduleGenerateFrame();
if (ShouldParentObserveEpoch()) {
mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
@ -664,7 +664,7 @@ WebRenderBridgeParent::RecvEmptyTransaction(const FocusTarget& aFocusTarget,
if (!aCommands.IsEmpty()) {
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
ProcessWebRenderParentCommands(aCommands);
mCompositorScheduler->ScheduleComposition();
ScheduleGenerateFrame();
}
mScrollData.SetFocusTarget(aFocusTarget);
@ -940,8 +940,8 @@ WebRenderBridgeParent::RecvClearCachedResources()
// Clear resources
mApi->ClearDisplayList(wr::NewEpoch(GetNextWrEpoch()), mPipelineId);
// Schedule composition to clean up Pipeline
mCompositorScheduler->ScheduleComposition();
// Schedule generate frame to clean up Pipeline
ScheduleGenerateFrame();
// Remove animations.
for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
mAnimStorage->ClearById(*iter);
@ -998,7 +998,7 @@ WebRenderBridgeParent::RecvForceComposite()
if (mDestroyed) {
return IPC_OK();
}
ScheduleComposition();
ScheduleGenerateFrame();
return IPC_OK();
}
@ -1189,24 +1189,36 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
if (!mForceRendering &&
wr::RenderThread::Get()->TooManyPendingFrames(mApi->GetId())) {
// Render thread is busy, try next time.
ScheduleComposition();
mCompositorScheduler->ScheduleComposition();
return;
}
bool scheduleComposite = false;
nsTArray<wr::WrOpacityProperty> opacityArray;
nsTArray<wr::WrTransformProperty> transformArray;
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
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);
if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
scheduleComposite = true;
ScheduleGenerateFrame();
}
if (PushAPZStateToWR(transformArray)) {
scheduleComposite = true;
ScheduleGenerateFrame();
}
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId());
@ -1221,14 +1233,6 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
} else {
mApi->GenerateFrame();
}
if (!mAsyncImageManager->GetCompositeUntilTime().IsNull()) {
scheduleComposite = true;
}
if (scheduleComposite) {
ScheduleComposition();
}
}
void
@ -1302,9 +1306,10 @@ WebRenderBridgeParent::GetLayersId() const
}
void
WebRenderBridgeParent::ScheduleComposition()
WebRenderBridgeParent::ScheduleGenerateFrame()
{
if (mCompositorScheduler) {
mAsyncImageManager->SetWillGenerateFrame();
mCompositorScheduler->ScheduleComposition();
}
}
@ -1368,8 +1373,8 @@ WebRenderBridgeParent::ClearResources()
uint32_t wrEpoch = GetNextWrEpoch();
mApi->ClearDisplayList(wr::NewEpoch(wrEpoch), mPipelineId);
// Schedule composition to clean up Pipeline
mCompositorScheduler->ScheduleComposition();
// Schedule generate frame to clean up Pipeline
ScheduleGenerateFrame();
// WrFontKeys and WrImageKeys are deleted during WebRenderAPI destruction.
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->ClearWrBridge();

Просмотреть файл

@ -173,7 +173,18 @@ public:
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,
wr::WebRenderAPI* aApi,

Просмотреть файл

@ -70,8 +70,9 @@ WebRenderImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
mImages.SwapElements(newImages);
newImages.Clear();
if (mWrBridge && GetAsyncRef()) {
mWrBridge->ScheduleComposition();
if (mWrBridge && mWrBridge->CompositorScheduler() && GetAsyncRef()) {
// Will check if we will generate frame.
mWrBridge->CompositorScheduler()->ScheduleComposition();
}
// Video producers generally send replacement images with the same frameID but