Bug 1476846 - Reduce latency of applying async images of video r=nical

This commit is contained in:
sotaro
2018-08-07 19:12:06 +09:00
parent 42670002fb
commit b7cb4c6c5b
3 changed files with 68 additions and 52 deletions

View File

@@ -179,9 +179,10 @@ AsyncImagePipelineManager::UpdateAsyncImagePipeline(const wr::PipelineId& aPipel
Maybe<TextureHost::ResourceUpdateOp>
AsyncImagePipelineManager::UpdateImageKeys(const wr::Epoch& aEpoch,
const wr::PipelineId& aPipelineId,
wr::TransactionBuilder& aResources,
AsyncImagePipeline* aPipeline,
nsTArray<wr::ImageKey>& aKeys)
nsTArray<wr::ImageKey>& aKeys,
wr::TransactionBuilder& aSceneBuilderTxn,
wr::TransactionBuilder& aMaybeFastTxn)
{
MOZ_ASSERT(aKeys.IsEmpty());
MOZ_ASSERT(aPipeline);
@@ -242,7 +243,9 @@ AsyncImagePipelineManager::UpdateImageKeys(const wr::Epoch& aEpoch,
if (!canUpdate) {
for (auto key : aPipeline->mKeys) {
aResources.DeleteImage(key);
// Destroy ImageKeys on transaction of scene builder thread, since DisplayList is
// updated on SceneBuilder thread. It prevents too early ImageKey deletion.
aSceneBuilderTxn.DeleteImage(key);
}
aPipeline->mKeys.Clear();
for (uint32_t i = 0; i < numKeys; ++i) {
@@ -255,7 +258,7 @@ AsyncImagePipelineManager::UpdateImageKeys(const wr::Epoch& aEpoch,
auto op = canUpdate ? TextureHost::UPDATE_IMAGE : TextureHost::ADD_IMAGE;
if (!useExternalImage) {
return UpdateWithoutExternalImage(aResources, texture, aKeys[0], op);
return UpdateWithoutExternalImage(texture, aKeys[0], op, aMaybeFastTxn);
}
if (useWrTextureWrapper && aPipeline->mWrTextureWrapper) {
@@ -273,7 +276,7 @@ AsyncImagePipelineManager::UpdateImageKeys(const wr::Epoch& aEpoch,
Range<wr::ImageKey> keys(&aKeys[0], aKeys.Length());
auto externalImageKey =
aPipeline->mWrTextureWrapper ? aPipeline->mWrTextureWrapper->GetExternalImageKey() : wrTexture->GetExternalImageKey();
wrTexture->PushResourceUpdates(aResources, op, keys, externalImageKey);
wrTexture->PushResourceUpdates(aMaybeFastTxn, op, keys, externalImageKey);
}
if (aPipeline->mWrTextureWrapper) {
@@ -284,10 +287,10 @@ AsyncImagePipelineManager::UpdateImageKeys(const wr::Epoch& aEpoch,
}
Maybe<TextureHost::ResourceUpdateOp>
AsyncImagePipelineManager::UpdateWithoutExternalImage(wr::TransactionBuilder& aResources,
TextureHost* aTexture,
AsyncImagePipelineManager::UpdateWithoutExternalImage(TextureHost* aTexture,
wr::ImageKey aKey,
TextureHost::ResourceUpdateOp aOp)
TextureHost::ResourceUpdateOp aOp,
wr::TransactionBuilder& aTxn)
{
MOZ_ASSERT(aTexture);
@@ -310,9 +313,9 @@ AsyncImagePipelineManager::UpdateWithoutExternalImage(wr::TransactionBuilder& aR
bytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
if (aOp == TextureHost::UPDATE_IMAGE) {
aResources.UpdateImageBuffer(aKey, descriptor, bytes);
aTxn.UpdateImageBuffer(aKey, descriptor, bytes);
} else {
aResources.AddImage(aKey, descriptor, bytes);
aTxn.AddImage(aKey, descriptor, bytes);
}
dSurf->Unmap();
@@ -321,7 +324,8 @@ AsyncImagePipelineManager::UpdateWithoutExternalImage(wr::TransactionBuilder& aR
}
void
AsyncImagePipelineManager::ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder& aTxn)
AsyncImagePipelineManager::ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder& aSceneBuilderTxn,
wr::TransactionBuilder& aFastTxn)
{
if (mDestroyed || mAsyncImagePipelines.Count() == 0) {
return;
@@ -338,7 +342,7 @@ AsyncImagePipelineManager::ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder&
if (!pipeline->mImageHost->GetAsyncRef()) {
continue;
}
ApplyAsyncImageForPipeline(epoch, pipelineId, pipeline, aTxn);
ApplyAsyncImageForPipeline(epoch, pipelineId, pipeline, aSceneBuilderTxn, aFastTxn);
}
}
@@ -346,23 +350,24 @@ void
AsyncImagePipelineManager::ApplyAsyncImageForPipeline(const wr::Epoch& aEpoch,
const wr::PipelineId& aPipelineId,
AsyncImagePipeline* aPipeline,
wr::TransactionBuilder& aTxn)
wr::TransactionBuilder& aSceneBuilderTxn,
wr::TransactionBuilder& aMaybeFastTxn)
{
nsTArray<wr::ImageKey> keys;
auto op = UpdateImageKeys(aEpoch, aPipelineId, aTxn, aPipeline, keys);
auto op = UpdateImageKeys(aEpoch, aPipelineId, aPipeline, keys, aSceneBuilderTxn, aMaybeFastTxn);
bool updateDisplayList = aPipeline->mInitialised &&
(aPipeline->mIsChanged || op == Some(TextureHost::ADD_IMAGE)) &&
!!aPipeline->mCurrentTexture;
// We will schedule generating a frame after the scene
// build is done or resource update is done, so we don't need to do it here.
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.
// We may, however, have updated some resources.
aTxn.UpdateEpoch(aPipelineId, aEpoch);
// Use transaction of scene builder thread to notify epoch.
// It is for making epoc update consisitent.
aMaybeFastTxn.UpdateEpoch(aPipelineId, aEpoch);
if (aPipeline->mCurrentTexture) {
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mCurrentTexture->AsWebRenderTextureHost());
}
@@ -419,23 +424,34 @@ AsyncImagePipelineManager::ApplyAsyncImageForPipeline(const wr::Epoch& aEpoch,
wr::BuiltDisplayList dl;
wr::LayoutSize builderContentSize;
builder.Finalize(builderContentSize, dl);
aTxn.SetDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f),
aEpoch,
LayerSize(aPipeline->mScBounds.Width(), aPipeline->mScBounds.Height()),
aPipelineId, builderContentSize,
dl.dl_desc, dl.dl);
aSceneBuilderTxn.SetDisplayList(
gfx::Color(0.f, 0.f, 0.f, 0.f),
aEpoch,
LayerSize(aPipeline->mScBounds.Width(), aPipeline->mScBounds.Height()),
aPipelineId, builderContentSize,
dl.dl_desc, dl.dl);
}
void
AsyncImagePipelineManager::ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn)
AsyncImagePipelineManager::ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aSceneBuilderTxn)
{
AsyncImagePipeline* pipeline = mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
if (!pipeline) {
return;
}
wr::TransactionBuilder fastTxn(/* aUseSceneBuilderThread */ false);
wr::AutoTransactionSender sender(mApi, &fastTxn);
// Use transaction of using non scene builder thread when ImageHost uses ImageBridge.
// ApplyAsyncImagesOfImageBridge() handles transaction of adding and updating
// wr::ImageKeys of ImageHosts that uses ImageBridge. Then AsyncImagePipelineManager
// always needs to use non scene builder thread transaction for adding and updating
// wr::ImageKeys of ImageHosts that uses ImageBridge. Otherwise, ordering of
// wr::ImageKeys updating in webrender becomes inconsistent.
auto& txn = pipeline->mImageHost->GetAsyncRef() ? fastTxn : aSceneBuilderTxn;
wr::Epoch epoch = GetNextImageEpoch();
ApplyAsyncImageForPipeline(epoch, aPipelineId, pipeline, aTxn);
ApplyAsyncImageForPipeline(epoch, aPipelineId, pipeline, aSceneBuilderTxn, txn);
}
void