2017-10-28 02:10:06 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
2017-01-20 05:26:13 +03:00
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
#include "AsyncImagePipelineManager.h"
|
2017-01-20 05:26:13 +03:00
|
|
|
|
|
|
|
#include "CompositableHost.h"
|
2017-07-17 08:38:22 +03:00
|
|
|
#include "gfxEnv.h"
|
2017-06-02 10:11:34 +03:00
|
|
|
#include "mozilla/gfx/gfxVars.h"
|
2017-11-30 15:38:47 +03:00
|
|
|
#include "mozilla/layers/CompositorThread.h"
|
2018-04-23 14:57:15 +03:00
|
|
|
#include "mozilla/layers/SharedSurfacesParent.h"
|
2017-03-07 13:37:28 +03:00
|
|
|
#include "mozilla/layers/WebRenderImageHost.h"
|
|
|
|
#include "mozilla/layers/WebRenderTextureHost.h"
|
2018-05-28 18:29:41 +03:00
|
|
|
#include "mozilla/webrender/RenderThread.h"
|
2017-05-17 03:28:20 +03:00
|
|
|
#include "mozilla/webrender/WebRenderAPI.h"
|
2017-09-26 16:30:55 +03:00
|
|
|
#include "mozilla/webrender/WebRenderTypes.h"
|
2017-01-20 05:26:13 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
|
2018-11-14 05:40:31 +03:00
|
|
|
AsyncImagePipelineManager::ForwardingExternalImage::~ForwardingExternalImage() {
|
|
|
|
DebugOnly<bool> released = SharedSurfacesParent::Release(mImageId);
|
|
|
|
MOZ_ASSERT(released);
|
|
|
|
}
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
AsyncImagePipelineManager::AsyncImagePipeline::AsyncImagePipeline()
|
2017-06-02 10:11:53 +03:00
|
|
|
: mInitialised(false),
|
2019-03-22 21:28:42 +03:00
|
|
|
mRenderRoot(wr::RenderRoot::Default),
|
2017-06-02 10:11:53 +03:00
|
|
|
mIsChanged(false),
|
2017-06-05 10:30:10 +03:00
|
|
|
mUseExternalImage(false),
|
2017-07-19 10:28:58 +03:00
|
|
|
mFilter(wr::ImageRendering::Auto),
|
|
|
|
mMixBlendMode(wr::MixBlendMode::Normal) {}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-11-16 16:01:01 +03:00
|
|
|
AsyncImagePipelineManager::PipelineUpdates::PipelineUpdates(
|
|
|
|
RefPtr<wr::WebRenderPipelineInfo> aPipelineInfo,
|
|
|
|
const uint64_t aUpdatesCount, const bool aRendered)
|
|
|
|
: mPipelineInfo(aPipelineInfo),
|
|
|
|
mUpdatesCount(aUpdatesCount),
|
|
|
|
mRendered(aRendered) {}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-08-09 15:46:25 +03:00
|
|
|
AsyncImagePipelineManager::AsyncImagePipelineManager(
|
2019-03-22 21:28:42 +03:00
|
|
|
nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis)
|
|
|
|
: mApis(aApis),
|
|
|
|
mIdNamespace(mApis[0]->GetNamespace()),
|
|
|
|
mUseTripleBuffering(mApis[0]->GetUseTripleBuffering()),
|
2017-05-09 11:19:48 +03:00
|
|
|
mResourceId(0),
|
2018-04-10 19:29:56 +03:00
|
|
|
mAsyncImageEpoch{0},
|
2019-03-22 21:28:42 +03:00
|
|
|
mWillGenerateFrame{},
|
2017-06-02 10:11:34 +03:00
|
|
|
mDestroyed(false),
|
2018-05-28 18:29:41 +03:00
|
|
|
mUpdatesLock("UpdatesLock"),
|
2018-10-31 08:19:41 +03:00
|
|
|
mUpdatesCount(0) {
|
2017-07-25 11:54:36 +03:00
|
|
|
MOZ_COUNT_CTOR(AsyncImagePipelineManager);
|
2017-01-20 05:26:13 +03:00
|
|
|
}
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
AsyncImagePipelineManager::~AsyncImagePipelineManager() {
|
|
|
|
MOZ_COUNT_DTOR(AsyncImagePipelineManager);
|
2017-01-20 05:26:13 +03:00
|
|
|
}
|
|
|
|
|
2017-08-09 15:46:25 +03:00
|
|
|
void AsyncImagePipelineManager::Destroy() {
|
|
|
|
MOZ_ASSERT(!mDestroyed);
|
2019-03-22 21:28:42 +03:00
|
|
|
mApis.Clear();
|
2018-11-14 05:40:31 +03:00
|
|
|
mPipelineTexturesHolders.Clear();
|
2017-06-02 10:11:34 +03:00
|
|
|
mDestroyed = true;
|
|
|
|
}
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
void AsyncImagePipelineManager::SetWillGenerateFrameAllRenderRoots() {
|
|
|
|
for (auto renderRoot : wr::kRenderRoots) {
|
|
|
|
SetWillGenerateFrame(renderRoot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsyncImagePipelineManager::SetWillGenerateFrame(
|
|
|
|
wr::RenderRoot aRenderRoot) {
|
2017-11-30 15:38:47 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
mWillGenerateFrame[aRenderRoot] = true;
|
2017-11-30 15:38:47 +03:00
|
|
|
}
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
bool AsyncImagePipelineManager::GetAndResetWillGenerateFrame(
|
|
|
|
wr::RenderRoot aRenderRoot) {
|
2017-11-30 15:38:47 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
bool ret = mWillGenerateFrame[aRenderRoot];
|
|
|
|
mWillGenerateFrame[aRenderRoot] = false;
|
2017-11-30 15:38:47 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:16:03 +03:00
|
|
|
wr::ExternalImageId AsyncImagePipelineManager::GetNextExternalImageId() {
|
|
|
|
static uint32_t sNextId = 0;
|
|
|
|
++sNextId;
|
|
|
|
MOZ_RELEASE_ASSERT(sNextId != UINT32_MAX);
|
|
|
|
// gecko allocates external image id as (IdNamespace:32bit +
|
|
|
|
// ResourceId:32bit). And AsyncImagePipelineManager uses IdNamespace = 0.
|
|
|
|
return wr::ToExternalImageId((uint64_t)sNextId);
|
|
|
|
}
|
|
|
|
|
2018-11-17 06:27:54 +03:00
|
|
|
void AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId,
|
|
|
|
WebRenderBridgeParent* aWrBridge) {
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-22 04:27:38 +03:00
|
|
|
uint64_t id = wr::AsUint64(aPipelineId);
|
|
|
|
|
2017-06-30 04:06:11 +03:00
|
|
|
PipelineTexturesHolder* holder =
|
|
|
|
mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
|
|
|
|
if (holder) {
|
|
|
|
// This could happen during tab move between different windows.
|
|
|
|
// Previously removed holder could be still alive for waiting destroyed.
|
|
|
|
MOZ_ASSERT(holder->mDestroyedEpoch.isSome());
|
|
|
|
holder->mDestroyedEpoch = Nothing(); // Revive holder
|
2018-11-17 06:27:54 +03:00
|
|
|
holder->mWrBridge = aWrBridge;
|
2017-06-30 04:06:11 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
holder = new PipelineTexturesHolder();
|
2018-11-17 06:27:54 +03:00
|
|
|
holder->mWrBridge = aWrBridge;
|
2017-03-22 04:27:38 +03:00
|
|
|
mPipelineTexturesHolders.Put(id, holder);
|
|
|
|
}
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
void AsyncImagePipelineManager::RemovePipeline(
|
|
|
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch) {
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-17 03:28:20 +03:00
|
|
|
PipelineTexturesHolder* holder =
|
|
|
|
mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
|
|
|
|
MOZ_ASSERT(holder);
|
|
|
|
if (!holder) {
|
|
|
|
return;
|
2017-03-07 13:37:28 +03:00
|
|
|
}
|
2018-11-17 06:27:54 +03:00
|
|
|
holder->mWrBridge = nullptr;
|
2017-05-17 03:28:20 +03:00
|
|
|
holder->mDestroyedEpoch = Some(aEpoch);
|
2017-01-20 05:26:13 +03:00
|
|
|
}
|
|
|
|
|
2018-11-17 06:27:54 +03:00
|
|
|
WebRenderBridgeParent* AsyncImagePipelineManager::GetWrBridge(
|
|
|
|
const wr::PipelineId& aPipelineId) {
|
|
|
|
if (mDestroyed) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
PipelineTexturesHolder* holder =
|
|
|
|
mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
|
|
|
|
if (!holder) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (holder->mWrBridge) {
|
|
|
|
MOZ_ASSERT(holder->mDestroyedEpoch.isNothing());
|
|
|
|
return holder->mWrBridge;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
void AsyncImagePipelineManager::AddAsyncImagePipeline(
|
2019-03-22 21:28:42 +03:00
|
|
|
const wr::PipelineId& aPipelineId, WebRenderImageHost* aImageHost,
|
|
|
|
wr::RenderRoot aRenderRoot) {
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(aImageHost);
|
|
|
|
uint64_t id = wr::AsUint64(aPipelineId);
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
MOZ_ASSERT(!mAsyncImagePipelines.Get(id));
|
|
|
|
AsyncImagePipeline* holder = new AsyncImagePipeline();
|
2019-03-22 21:28:42 +03:00
|
|
|
holder->mRenderRoot = aRenderRoot;
|
2017-06-02 10:11:34 +03:00
|
|
|
holder->mImageHost = aImageHost;
|
2017-07-25 11:54:36 +03:00
|
|
|
mAsyncImagePipelines.Put(id, holder);
|
2018-11-19 06:15:55 +03:00
|
|
|
AddPipeline(aPipelineId, /* aWrBridge */ nullptr);
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
|
|
|
|
2018-01-12 14:24:07 +03:00
|
|
|
void AsyncImagePipelineManager::RemoveAsyncImagePipeline(
|
|
|
|
const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn) {
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t id = wr::AsUint64(aPipelineId);
|
2017-07-25 11:54:36 +03:00
|
|
|
if (auto entry = mAsyncImagePipelines.Lookup(id)) {
|
|
|
|
AsyncImagePipeline* holder = entry.Data();
|
2018-04-10 19:29:56 +03:00
|
|
|
wr::Epoch epoch = GetNextImageEpoch();
|
|
|
|
aTxn.ClearDisplayList(epoch, aPipelineId);
|
2017-06-28 02:03:16 +03:00
|
|
|
for (wr::ImageKey key : holder->mKeys) {
|
2018-01-29 16:33:39 +03:00
|
|
|
aTxn.DeleteImage(key);
|
2017-06-28 02:03:16 +03:00
|
|
|
}
|
|
|
|
entry.Remove();
|
2018-04-10 19:29:56 +03:00
|
|
|
RemovePipeline(aPipelineId, epoch);
|
2017-06-02 10:11:53 +03:00
|
|
|
}
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
void AsyncImagePipelineManager::UpdateAsyncImagePipeline(
|
2018-11-29 22:22:37 +03:00
|
|
|
const wr::PipelineId& aPipelineId, const LayoutDeviceRect& aScBounds,
|
2017-07-25 11:54:36 +03:00
|
|
|
const gfx::Matrix4x4& aScTransform, const gfx::MaybeIntSize& aScaleToSize,
|
|
|
|
const wr::ImageRendering& aFilter, const wr::MixBlendMode& aMixBlendMode) {
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
2017-07-25 11:54:36 +03:00
|
|
|
AsyncImagePipeline* pipeline =
|
|
|
|
mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
|
|
|
|
if (!pipeline) {
|
2017-06-02 10:11:34 +03:00
|
|
|
return;
|
|
|
|
}
|
2017-07-25 11:54:36 +03:00
|
|
|
pipeline->mInitialised = true;
|
2018-11-29 22:22:37 +03:00
|
|
|
pipeline->Update(aScBounds, aScTransform, aScaleToSize, aFilter,
|
2017-11-15 04:14:06 +03:00
|
|
|
aMixBlendMode);
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
|
|
|
|
2018-07-25 17:30:08 +03:00
|
|
|
Maybe<TextureHost::ResourceUpdateOp> AsyncImagePipelineManager::UpdateImageKeys(
|
|
|
|
const wr::Epoch& aEpoch, const wr::PipelineId& aPipelineId,
|
2018-08-07 13:12:06 +03:00
|
|
|
AsyncImagePipeline* aPipeline, nsTArray<wr::ImageKey>& aKeys,
|
|
|
|
wr::TransactionBuilder& aSceneBuilderTxn,
|
|
|
|
wr::TransactionBuilder& aMaybeFastTxn) {
|
2017-06-02 10:11:34 +03:00
|
|
|
MOZ_ASSERT(aKeys.IsEmpty());
|
2017-09-26 16:30:55 +03:00
|
|
|
MOZ_ASSERT(aPipeline);
|
|
|
|
|
|
|
|
TextureHost* texture = aPipeline->mImageHost->GetAsTextureHostForComposite();
|
|
|
|
TextureHost* previousTexture = aPipeline->mCurrentTexture.get();
|
|
|
|
|
2017-10-30 16:15:35 +03:00
|
|
|
if (texture == previousTexture) {
|
2017-09-26 16:30:55 +03:00
|
|
|
// The texture has not changed, just reuse previous ImageKeys.
|
2017-10-30 16:15:35 +03:00
|
|
|
aKeys = aPipeline->mKeys;
|
2018-07-25 17:30:08 +03:00
|
|
|
if (aPipeline->mWrTextureWrapper) {
|
|
|
|
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mWrTextureWrapper);
|
|
|
|
}
|
2017-09-26 16:30:55 +03:00
|
|
|
return Nothing();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!texture) {
|
|
|
|
// We don't have a new texture, there isn't much we can do.
|
2017-10-30 16:15:35 +03:00
|
|
|
aKeys = aPipeline->mKeys;
|
2018-07-25 17:30:08 +03:00
|
|
|
if (aPipeline->mWrTextureWrapper) {
|
|
|
|
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mWrTextureWrapper);
|
|
|
|
}
|
2017-09-26 16:30:55 +03:00
|
|
|
return Nothing();
|
|
|
|
}
|
|
|
|
|
|
|
|
aPipeline->mCurrentTexture = texture;
|
|
|
|
|
|
|
|
WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
|
2019-03-07 19:15:17 +03:00
|
|
|
MOZ_ASSERT(wrTexture);
|
|
|
|
if (!wrTexture) {
|
|
|
|
gfxCriticalNote << "WebRenderTextureHost is not used";
|
|
|
|
}
|
2017-09-26 16:30:55 +03:00
|
|
|
|
|
|
|
bool useExternalImage = !gfxEnv::EnableWebRenderRecording() && wrTexture;
|
|
|
|
aPipeline->mUseExternalImage = useExternalImage;
|
|
|
|
|
2018-07-25 17:30:08 +03:00
|
|
|
// Use WebRenderTextureHostWrapper only for video.
|
|
|
|
// And WebRenderTextureHostWrapper could be used only with
|
|
|
|
// WebRenderTextureHost that supports NativeTexture
|
2019-03-13 12:19:06 +03:00
|
|
|
bool useWrTextureWrapper =
|
|
|
|
useExternalImage && wrTexture && wrTexture->SupportsWrNativeTexture();
|
2018-07-25 17:30:08 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
// The non-external image code path falls back to converting the texture into
|
|
|
|
// an rgb image.
|
|
|
|
auto numKeys = useExternalImage ? texture->NumSubTextures() : 1;
|
2017-06-02 10:11:34 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
// If we already had a texture and the format hasn't changed, better to reuse
|
|
|
|
// the image keys than create new ones.
|
|
|
|
bool canUpdate = !!previousTexture &&
|
2017-11-22 03:52:22 +03:00
|
|
|
previousTexture->GetSize() == texture->GetSize() &&
|
2017-09-26 16:30:55 +03:00
|
|
|
previousTexture->GetFormat() == texture->GetFormat() &&
|
|
|
|
aPipeline->mKeys.Length() == numKeys;
|
2017-06-02 10:11:34 +03:00
|
|
|
|
2018-07-25 17:30:08 +03:00
|
|
|
// Check if WebRenderTextureHostWrapper could be reused.
|
|
|
|
if (aPipeline->mWrTextureWrapper && (!useWrTextureWrapper || !canUpdate)) {
|
|
|
|
aPipeline->mWrTextureWrapper = nullptr;
|
|
|
|
canUpdate = false;
|
|
|
|
}
|
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
if (!canUpdate) {
|
2017-09-26 16:31:08 +03:00
|
|
|
for (auto key : aPipeline->mKeys) {
|
2018-08-07 13:12:06 +03:00
|
|
|
// Destroy ImageKeys on transaction of scene builder thread, since
|
|
|
|
// DisplayList is updated on SceneBuilder thread. It prevents too early
|
|
|
|
// ImageKey deletion.
|
|
|
|
aSceneBuilderTxn.DeleteImage(key);
|
2017-09-26 16:31:08 +03:00
|
|
|
}
|
2017-09-26 16:30:55 +03:00
|
|
|
aPipeline->mKeys.Clear();
|
2017-09-26 16:30:46 +03:00
|
|
|
for (uint32_t i = 0; i < numKeys; ++i) {
|
2017-09-26 16:30:55 +03:00
|
|
|
aPipeline->mKeys.AppendElement(GenerateImageKey());
|
2017-09-26 16:30:46 +03:00
|
|
|
}
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
aKeys = aPipeline->mKeys;
|
2017-06-02 10:11:53 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
auto op = canUpdate ? TextureHost::UPDATE_IMAGE : TextureHost::ADD_IMAGE;
|
2017-06-02 10:11:53 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
if (!useExternalImage) {
|
2018-08-07 13:12:06 +03:00
|
|
|
return UpdateWithoutExternalImage(texture, aKeys[0], op, aMaybeFastTxn);
|
2017-06-02 10:11:53 +03:00
|
|
|
}
|
|
|
|
|
2018-07-25 17:30:08 +03:00
|
|
|
if (useWrTextureWrapper && aPipeline->mWrTextureWrapper) {
|
|
|
|
MOZ_ASSERT(canUpdate);
|
|
|
|
// Reuse WebRenderTextureHostWrapper. With it, rendered frame could be
|
|
|
|
// updated without batch re-creation.
|
2019-03-13 12:19:06 +03:00
|
|
|
aPipeline->mWrTextureWrapper->UpdateWebRenderTextureHost(aMaybeFastTxn,
|
|
|
|
wrTexture);
|
2018-07-25 17:30:08 +03:00
|
|
|
// Ensure frame generation.
|
2019-03-22 21:28:42 +03:00
|
|
|
SetWillGenerateFrame(aPipeline->mRenderRoot);
|
2018-07-25 17:30:08 +03:00
|
|
|
} else {
|
|
|
|
if (useWrTextureWrapper) {
|
|
|
|
aPipeline->mWrTextureWrapper = new WebRenderTextureHostWrapper(this);
|
2019-03-13 12:19:06 +03:00
|
|
|
aPipeline->mWrTextureWrapper->UpdateWebRenderTextureHost(aMaybeFastTxn,
|
|
|
|
wrTexture);
|
2018-07-25 17:30:08 +03:00
|
|
|
}
|
|
|
|
Range<wr::ImageKey> keys(&aKeys[0], aKeys.Length());
|
|
|
|
auto externalImageKey =
|
|
|
|
aPipeline->mWrTextureWrapper
|
|
|
|
? aPipeline->mWrTextureWrapper->GetExternalImageKey()
|
|
|
|
: wrTexture->GetExternalImageKey();
|
2018-08-07 13:12:06 +03:00
|
|
|
wrTexture->PushResourceUpdates(aMaybeFastTxn, op, keys, externalImageKey);
|
2018-07-25 17:30:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aPipeline->mWrTextureWrapper) {
|
2018-10-10 06:20:23 +03:00
|
|
|
// Force frame rendering, since WebRenderTextureHost update its data outside
|
|
|
|
// of WebRender.
|
|
|
|
aMaybeFastTxn.InvalidateRenderedFrame();
|
2018-07-25 17:30:08 +03:00
|
|
|
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mWrTextureWrapper);
|
|
|
|
}
|
2017-09-26 16:30:55 +03:00
|
|
|
|
|
|
|
return Some(op);
|
|
|
|
}
|
2017-06-02 10:11:53 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
Maybe<TextureHost::ResourceUpdateOp>
|
2018-08-07 13:12:06 +03:00
|
|
|
AsyncImagePipelineManager::UpdateWithoutExternalImage(
|
|
|
|
TextureHost* aTexture, wr::ImageKey aKey, TextureHost::ResourceUpdateOp aOp,
|
|
|
|
wr::TransactionBuilder& aTxn) {
|
2017-09-26 16:30:55 +03:00
|
|
|
MOZ_ASSERT(aTexture);
|
|
|
|
|
|
|
|
RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
|
|
|
|
if (!dSurf) {
|
|
|
|
NS_ERROR("TextureHost does not return DataSourceSurface");
|
|
|
|
return Nothing();
|
|
|
|
}
|
|
|
|
gfx::DataSourceSurface::MappedSurface map;
|
|
|
|
if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
|
|
|
|
NS_ERROR("DataSourceSurface failed to map");
|
|
|
|
return Nothing();
|
2017-06-02 10:11:53 +03:00
|
|
|
}
|
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
gfx::IntSize size = dSurf->GetSize();
|
|
|
|
wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
|
2017-06-02 10:11:53 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
// Costly copy right here...
|
2018-01-04 21:23:34 +03:00
|
|
|
wr::Vec<uint8_t> bytes;
|
2017-09-26 16:30:55 +03:00
|
|
|
bytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
|
|
|
|
|
|
|
|
if (aOp == TextureHost::UPDATE_IMAGE) {
|
2018-08-07 13:12:06 +03:00
|
|
|
aTxn.UpdateImageBuffer(aKey, descriptor, bytes);
|
2017-09-26 16:30:55 +03:00
|
|
|
} else {
|
2018-08-07 13:12:06 +03:00
|
|
|
aTxn.AddImage(aKey, descriptor, bytes);
|
2017-06-02 10:11:53 +03:00
|
|
|
}
|
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
dSurf->Unmap();
|
|
|
|
|
|
|
|
return Some(aOp);
|
2017-06-02 10:11:53 +03:00
|
|
|
}
|
|
|
|
|
2018-08-07 13:12:06 +03:00
|
|
|
void AsyncImagePipelineManager::ApplyAsyncImagesOfImageBridge(
|
2019-03-22 21:28:42 +03:00
|
|
|
wr::RenderRootArray<Maybe<wr::TransactionBuilder>>& aSceneBuilderTxns,
|
|
|
|
wr::RenderRootArray<Maybe<wr::TransactionBuilder>>& aFastTxns) {
|
2017-07-25 11:54:36 +03:00
|
|
|
if (mDestroyed || mAsyncImagePipelines.Count() == 0) {
|
2017-06-02 10:11:34 +03:00
|
|
|
return;
|
|
|
|
}
|
2017-06-02 10:11:53 +03:00
|
|
|
|
2018-04-10 19:29:56 +03:00
|
|
|
wr::Epoch epoch = GetNextImageEpoch();
|
2017-06-02 10:11:34 +03:00
|
|
|
|
2017-09-26 16:30:55 +03:00
|
|
|
// We use a pipeline with a very small display list for each video element.
|
|
|
|
// Update each of them if needed.
|
2017-07-25 11:54:36 +03:00
|
|
|
for (auto iter = mAsyncImagePipelines.Iter(); !iter.Done(); iter.Next()) {
|
2017-06-02 10:11:34 +03:00
|
|
|
wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
|
2017-07-25 11:54:36 +03:00
|
|
|
AsyncImagePipeline* pipeline = iter.Data();
|
2018-07-19 01:51:37 +03:00
|
|
|
// If aync image pipeline does not use ImageBridge, do not need to apply.
|
|
|
|
if (!pipeline->mImageHost->GetAsyncRef()) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-03-22 21:28:42 +03:00
|
|
|
ApplyAsyncImageForPipeline(epoch, pipelineId, pipeline,
|
|
|
|
*aSceneBuilderTxns[pipeline->mRenderRoot],
|
|
|
|
*aFastTxns[pipeline->mRenderRoot]);
|
2018-07-19 01:51:37 +03:00
|
|
|
}
|
|
|
|
}
|
2017-06-02 10:11:34 +03:00
|
|
|
|
2018-07-19 01:51:37 +03:00
|
|
|
void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
|
|
|
|
const wr::Epoch& aEpoch, const wr::PipelineId& aPipelineId,
|
2018-08-07 13:12:06 +03:00
|
|
|
AsyncImagePipeline* aPipeline, wr::TransactionBuilder& aSceneBuilderTxn,
|
|
|
|
wr::TransactionBuilder& aMaybeFastTxn) {
|
2018-07-19 01:51:37 +03:00
|
|
|
nsTArray<wr::ImageKey> keys;
|
2018-08-07 13:12:06 +03:00
|
|
|
auto op = UpdateImageKeys(aEpoch, aPipelineId, aPipeline, keys,
|
|
|
|
aSceneBuilderTxn, aMaybeFastTxn);
|
2018-07-19 01:51:37 +03:00
|
|
|
|
|
|
|
bool updateDisplayList =
|
|
|
|
aPipeline->mInitialised &&
|
|
|
|
(aPipeline->mIsChanged || op == Some(TextureHost::ADD_IMAGE)) &&
|
|
|
|
!!aPipeline->mCurrentTexture;
|
|
|
|
|
|
|
|
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.
|
2018-08-07 13:12:06 +03:00
|
|
|
|
|
|
|
// Use transaction of scene builder thread to notify epoch.
|
2018-08-08 08:14:00 +03:00
|
|
|
// It is for making epoch update consistent.
|
|
|
|
aSceneBuilderTxn.UpdateEpoch(aPipelineId, aEpoch);
|
2018-07-19 01:51:37 +03:00
|
|
|
if (aPipeline->mCurrentTexture) {
|
2019-03-13 12:19:06 +03:00
|
|
|
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mCurrentTexture);
|
2018-05-24 16:59:28 +03:00
|
|
|
}
|
2018-07-19 01:51:37 +03:00
|
|
|
return;
|
|
|
|
}
|
2018-05-24 16:59:28 +03:00
|
|
|
|
2018-07-19 01:51:37 +03:00
|
|
|
aPipeline->mIsChanged = false;
|
2018-11-29 22:22:37 +03:00
|
|
|
|
|
|
|
wr::LayoutSize contentSize{aPipeline->mScBounds.Width(),
|
|
|
|
aPipeline->mScBounds.Height()};
|
|
|
|
wr::DisplayListBuilder builder(aPipelineId, contentSize);
|
2018-07-19 01:51:37 +03:00
|
|
|
|
|
|
|
float opacity = 1.0f;
|
2019-01-23 04:08:34 +03:00
|
|
|
wr::StackingContextParams params;
|
|
|
|
params.opacity = &opacity;
|
|
|
|
params.mTransformPtr =
|
|
|
|
aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform;
|
|
|
|
params.mix_blend_mode = aPipeline->mMixBlendMode;
|
|
|
|
|
2019-01-09 06:27:07 +03:00
|
|
|
Maybe<wr::WrSpatialId> referenceFrameId = builder.PushStackingContext(
|
2019-01-23 04:08:34 +03:00
|
|
|
params, wr::ToRoundedLayoutRect(aPipeline->mScBounds),
|
2018-07-19 01:51:37 +03:00
|
|
|
// This is fine to do unconditionally because we only push images here.
|
2018-09-23 04:19:52 +03:00
|
|
|
wr::RasterSpace::Screen());
|
2018-07-19 01:51:37 +03:00
|
|
|
|
2019-01-09 06:27:07 +03:00
|
|
|
Maybe<wr::SpaceAndClipChainHelper> spaceAndClipChainHelper;
|
|
|
|
if (referenceFrameId) {
|
|
|
|
spaceAndClipChainHelper.emplace(builder, referenceFrameId.ref());
|
|
|
|
}
|
|
|
|
|
2018-07-19 01:51:37 +03:00
|
|
|
if (aPipeline->mCurrentTexture && !keys.IsEmpty()) {
|
|
|
|
LayoutDeviceRect rect(0, 0, aPipeline->mCurrentTexture->GetSize().width,
|
|
|
|
aPipeline->mCurrentTexture->GetSize().height);
|
|
|
|
if (aPipeline->mScaleToSize.isSome()) {
|
|
|
|
rect = LayoutDeviceRect(0, 0, aPipeline->mScaleToSize.value().width,
|
|
|
|
aPipeline->mScaleToSize.value().height);
|
2017-06-02 10:11:53 +03:00
|
|
|
}
|
2018-05-24 16:59:28 +03:00
|
|
|
|
2018-07-19 01:51:37 +03:00
|
|
|
if (aPipeline->mUseExternalImage) {
|
|
|
|
MOZ_ASSERT(aPipeline->mCurrentTexture->AsWebRenderTextureHost());
|
|
|
|
Range<wr::ImageKey> range_keys(&keys[0], keys.Length());
|
|
|
|
aPipeline->mCurrentTexture->PushDisplayItems(
|
2018-09-26 03:18:21 +03:00
|
|
|
builder, wr::ToRoundedLayoutRect(rect), wr::ToRoundedLayoutRect(rect),
|
2018-07-19 01:51:37 +03:00
|
|
|
aPipeline->mFilter, range_keys);
|
2019-03-13 12:19:06 +03:00
|
|
|
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mCurrentTexture);
|
2018-07-19 01:51:37 +03:00
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(keys.Length() == 1);
|
2018-09-26 03:18:21 +03:00
|
|
|
builder.PushImage(wr::ToRoundedLayoutRect(rect),
|
|
|
|
wr::ToRoundedLayoutRect(rect), true, aPipeline->mFilter,
|
2018-07-19 01:51:37 +03:00
|
|
|
keys[0]);
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
2018-07-19 01:51:37 +03:00
|
|
|
}
|
2018-05-24 16:59:28 +03:00
|
|
|
|
2019-01-09 06:27:07 +03:00
|
|
|
spaceAndClipChainHelper.reset();
|
2018-07-19 01:51:37 +03:00
|
|
|
builder.PopStackingContext(referenceFrameId.isSome());
|
2017-06-02 10:11:34 +03:00
|
|
|
|
2018-07-19 01:51:37 +03:00
|
|
|
wr::BuiltDisplayList dl;
|
|
|
|
wr::LayoutSize builderContentSize;
|
|
|
|
builder.Finalize(builderContentSize, dl);
|
2019-03-30 09:41:48 +03:00
|
|
|
aSceneBuilderTxn.SetDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), aEpoch,
|
|
|
|
wr::ToLayoutSize(aPipeline->mScBounds.Size()),
|
|
|
|
aPipelineId, builderContentSize, dl.dl_desc,
|
|
|
|
dl.dl);
|
2018-07-19 01:51:37 +03:00
|
|
|
}
|
|
|
|
|
2018-09-26 05:45:30 +03:00
|
|
|
void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
|
|
|
|
const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn,
|
2019-03-22 21:28:42 +03:00
|
|
|
wr::TransactionBuilder& aTxnForImageBridge, wr::RenderRoot aRenderRoot) {
|
2018-07-19 01:51:37 +03:00
|
|
|
AsyncImagePipeline* pipeline =
|
|
|
|
mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
|
|
|
|
if (!pipeline) {
|
|
|
|
return;
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
2019-03-22 21:28:42 +03:00
|
|
|
wr::WebRenderAPI* api = mApis[(size_t)pipeline->mRenderRoot];
|
2018-08-07 13:12:06 +03:00
|
|
|
wr::TransactionBuilder fastTxn(/* aUseSceneBuilderThread */ false);
|
2019-03-22 21:28:42 +03:00
|
|
|
wr::AutoTransactionSender sender(api, &fastTxn);
|
2018-08-07 13:12:06 +03:00
|
|
|
|
2018-09-26 05:45:30 +03:00
|
|
|
// Transaction for async image pipeline that uses ImageBridge always need to
|
|
|
|
// be non low priority.
|
|
|
|
auto& sceneBuilderTxn =
|
|
|
|
pipeline->mImageHost->GetAsyncRef() ? aTxnForImageBridge : aTxn;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-08-07 13:12:06 +03:00
|
|
|
// 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.
|
2018-09-26 05:45:30 +03:00
|
|
|
auto& maybeFastTxn = pipeline->mImageHost->GetAsyncRef() ? fastTxn : aTxn;
|
2018-07-19 01:51:37 +03:00
|
|
|
|
|
|
|
wr::Epoch epoch = GetNextImageEpoch();
|
2018-09-26 05:45:30 +03:00
|
|
|
|
|
|
|
ApplyAsyncImageForPipeline(epoch, aPipelineId, pipeline, sceneBuilderTxn,
|
|
|
|
maybeFastTxn);
|
2018-07-19 01:51:37 +03:00
|
|
|
}
|
|
|
|
|
2018-09-26 05:45:30 +03:00
|
|
|
void AsyncImagePipelineManager::SetEmptyDisplayList(
|
|
|
|
const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn,
|
|
|
|
wr::TransactionBuilder& aTxnForImageBridge) {
|
2018-07-19 01:51:37 +03:00
|
|
|
AsyncImagePipeline* pipeline =
|
|
|
|
mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
|
|
|
|
if (!pipeline) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-26 05:45:30 +03:00
|
|
|
// Transaction for async image pipeline that uses ImageBridge always need to
|
|
|
|
// be non low priority.
|
|
|
|
auto& txn = pipeline->mImageHost->GetAsyncRef() ? aTxnForImageBridge : aTxn;
|
|
|
|
|
2018-07-19 01:51:37 +03:00
|
|
|
wr::Epoch epoch = GetNextImageEpoch();
|
2018-11-29 22:22:37 +03:00
|
|
|
wr::LayoutSize contentSize{pipeline->mScBounds.Width(),
|
|
|
|
pipeline->mScBounds.Height()};
|
|
|
|
wr::DisplayListBuilder builder(aPipelineId, contentSize);
|
2018-07-19 01:51:37 +03:00
|
|
|
|
|
|
|
wr::BuiltDisplayList dl;
|
|
|
|
wr::LayoutSize builderContentSize;
|
|
|
|
builder.Finalize(builderContentSize, dl);
|
2019-03-30 09:41:48 +03:00
|
|
|
txn.SetDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch,
|
|
|
|
wr::ToLayoutSize(pipeline->mScBounds.Size()), aPipelineId,
|
|
|
|
builderContentSize, dl.dl_desc, dl.dl);
|
2017-06-02 10:11:34 +03:00
|
|
|
}
|
|
|
|
|
2017-07-25 11:54:36 +03:00
|
|
|
void AsyncImagePipelineManager::HoldExternalImage(
|
|
|
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
2019-03-07 19:15:17 +03:00
|
|
|
TextureHost* aTexture) {
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-07 13:37:28 +03:00
|
|
|
MOZ_ASSERT(aTexture);
|
2017-05-17 03:28:20 +03:00
|
|
|
|
2017-03-22 04:27:38 +03:00
|
|
|
PipelineTexturesHolder* holder =
|
|
|
|
mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
|
|
|
|
MOZ_ASSERT(holder);
|
|
|
|
if (!holder) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-07 13:37:28 +03:00
|
|
|
// Hold WebRenderTextureHost until end of its usage on RenderThread
|
2017-03-22 04:27:38 +03:00
|
|
|
holder->mTextureHosts.push(ForwardingTextureHost(aEpoch, aTexture));
|
2017-01-20 05:26:13 +03:00
|
|
|
}
|
|
|
|
|
2018-07-25 17:30:08 +03:00
|
|
|
void AsyncImagePipelineManager::HoldExternalImage(
|
|
|
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
|
|
|
WebRenderTextureHostWrapper* aWrTextureWrapper) {
|
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(aWrTextureWrapper);
|
|
|
|
|
|
|
|
PipelineTexturesHolder* holder =
|
|
|
|
mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
|
|
|
|
MOZ_ASSERT(holder);
|
|
|
|
if (!holder) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Hold WebRenderTextureHostWrapper until end of its usage on RenderThread
|
|
|
|
holder->mTextureHostWrappers.push(
|
|
|
|
ForwardingTextureHostWrapper(aEpoch, aWrTextureWrapper));
|
|
|
|
}
|
|
|
|
|
2018-04-23 14:57:15 +03:00
|
|
|
void AsyncImagePipelineManager::HoldExternalImage(
|
|
|
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
|
|
|
const wr::ExternalImageId& aImageId) {
|
|
|
|
if (mDestroyed) {
|
|
|
|
SharedSurfacesParent::Release(aImageId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PipelineTexturesHolder* holder =
|
|
|
|
mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
|
|
|
|
MOZ_ASSERT(holder);
|
|
|
|
if (!holder) {
|
|
|
|
SharedSurfacesParent::Release(aImageId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-14 05:40:31 +03:00
|
|
|
auto image = MakeUnique<ForwardingExternalImage>(aEpoch, aImageId);
|
|
|
|
holder->mExternalImages.push(std::move(image));
|
2018-04-23 14:57:15 +03:00
|
|
|
}
|
|
|
|
|
2018-11-16 16:01:01 +03:00
|
|
|
void AsyncImagePipelineManager::NotifyPipelinesUpdated(
|
|
|
|
RefPtr<wr::WebRenderPipelineInfo> aInfo, bool aRender) {
|
2018-05-28 18:29:41 +03:00
|
|
|
// This is called on the render thread, so we just stash the data into
|
2018-10-31 08:19:41 +03:00
|
|
|
// UpdatesQueue and process it later on the compositor thread.
|
2018-05-28 18:29:41 +03:00
|
|
|
MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
|
|
|
|
|
2018-10-31 08:19:41 +03:00
|
|
|
// Increment the count when render happens.
|
|
|
|
uint64_t currCount = aRender ? ++mUpdatesCount : mUpdatesCount;
|
2018-11-16 16:01:01 +03:00
|
|
|
auto updates = MakeUnique<PipelineUpdates>(aInfo, currCount, aRender);
|
2018-10-31 08:19:41 +03:00
|
|
|
|
|
|
|
{
|
|
|
|
// Scope lock to push UpdatesQueue to mUpdatesQueues.
|
|
|
|
MutexAutoLock lock(mUpdatesLock);
|
|
|
|
mUpdatesQueues.push(std::move(updates));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!aRender) {
|
|
|
|
// Do not post ProcessPipelineUpdate when rendering did not happen.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-28 18:29:41 +03:00
|
|
|
// Queue a runnable on the compositor thread to process the queue
|
|
|
|
layers::CompositorThreadHolder::Loop()->PostTask(
|
|
|
|
NewRunnableMethod("ProcessPipelineUpdates", this,
|
|
|
|
&AsyncImagePipelineManager::ProcessPipelineUpdates));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsyncImagePipelineManager::ProcessPipelineUpdates() {
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
|
2017-06-02 10:11:34 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
2018-05-28 18:29:41 +03:00
|
|
|
|
2018-10-31 08:19:41 +03:00
|
|
|
UniquePtr<PipelineUpdates> updates;
|
|
|
|
|
2018-05-28 18:29:41 +03:00
|
|
|
while (true) {
|
2018-11-16 16:01:01 +03:00
|
|
|
{
|
2018-10-31 08:19:41 +03:00
|
|
|
// Scope lock to extract UpdatesQueue from mUpdatesQueues.
|
2018-05-28 18:29:41 +03:00
|
|
|
MutexAutoLock lock(mUpdatesLock);
|
2018-10-31 08:19:41 +03:00
|
|
|
if (mUpdatesQueues.empty()) {
|
|
|
|
// No more PipelineUpdates to process for now.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Check if PipelineUpdates is ready to process.
|
|
|
|
uint64_t currCount = mUpdatesCount;
|
|
|
|
if (mUpdatesQueues.front()->NeedsToWait(currCount)) {
|
|
|
|
// PipelineUpdates is not ready for processing for now.
|
2018-05-28 18:29:41 +03:00
|
|
|
break;
|
|
|
|
}
|
2018-10-31 08:19:41 +03:00
|
|
|
updates = std::move(mUpdatesQueues.front());
|
|
|
|
mUpdatesQueues.pop();
|
2018-05-28 18:29:41 +03:00
|
|
|
}
|
2018-10-31 08:19:41 +03:00
|
|
|
MOZ_ASSERT(updates);
|
|
|
|
|
2018-11-16 16:01:01 +03:00
|
|
|
auto& info = updates->mPipelineInfo->Raw();
|
2018-05-28 18:29:41 +03:00
|
|
|
|
2018-11-16 16:01:01 +03:00
|
|
|
for (uintptr_t i = 0; i < info.epochs.length; i++) {
|
|
|
|
ProcessPipelineRendered(info.epochs.data[i].pipeline_id,
|
|
|
|
info.epochs.data[i].epoch,
|
|
|
|
updates->mUpdatesCount);
|
|
|
|
}
|
|
|
|
for (uintptr_t i = 0; i < info.removed_pipelines.length; i++) {
|
|
|
|
ProcessPipelineRemoved(info.removed_pipelines.data[i],
|
|
|
|
updates->mUpdatesCount);
|
2018-05-28 18:29:41 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-05 12:58:37 +03:00
|
|
|
CheckForTextureHostsNotUsedByGPU();
|
2018-05-28 18:29:41 +03:00
|
|
|
}
|
|
|
|
|
2018-11-05 12:58:37 +03:00
|
|
|
void AsyncImagePipelineManager::ProcessPipelineRendered(
|
|
|
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
|
|
|
const uint64_t aUpdatesCount) {
|
2017-06-28 02:03:16 +03:00
|
|
|
if (auto entry = mPipelineTexturesHolders.Lookup(wr::AsUint64(aPipelineId))) {
|
|
|
|
PipelineTexturesHolder* holder = entry.Data();
|
|
|
|
// Release TextureHosts based on Epoch
|
|
|
|
while (!holder->mTextureHosts.empty()) {
|
|
|
|
if (aEpoch <= holder->mTextureHosts.front().mEpoch) {
|
|
|
|
break;
|
|
|
|
}
|
2018-11-05 12:58:37 +03:00
|
|
|
// Need to extend holding TextureHost if it is direct bounded texture.
|
|
|
|
HoldUntilNotUsedByGPU(holder->mTextureHosts.front().mTexture,
|
|
|
|
aUpdatesCount);
|
2017-06-28 02:03:16 +03:00
|
|
|
holder->mTextureHosts.pop();
|
2017-03-07 13:37:28 +03:00
|
|
|
}
|
2018-07-25 17:30:08 +03:00
|
|
|
while (!holder->mTextureHostWrappers.empty()) {
|
|
|
|
if (aEpoch <= holder->mTextureHostWrappers.front().mEpoch) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
holder->mTextureHostWrappers.pop();
|
|
|
|
}
|
2018-04-23 14:57:15 +03:00
|
|
|
while (!holder->mExternalImages.empty()) {
|
2018-11-14 05:40:31 +03:00
|
|
|
if (aEpoch <= holder->mExternalImages.front()->mEpoch) {
|
2018-04-23 14:57:15 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
holder->mExternalImages.pop();
|
|
|
|
}
|
2017-01-20 05:26:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 12:58:37 +03:00
|
|
|
void AsyncImagePipelineManager::ProcessPipelineRemoved(
|
2019-03-22 21:28:42 +03:00
|
|
|
const wr::RemovedPipeline& aRemovedPipeline, const uint64_t aUpdatesCount) {
|
2018-02-12 19:37:02 +03:00
|
|
|
if (mDestroyed) {
|
|
|
|
return;
|
|
|
|
}
|
2019-03-22 21:28:42 +03:00
|
|
|
if (auto entry = mPipelineTexturesHolders.Lookup(
|
|
|
|
wr::AsUint64(aRemovedPipeline.pipeline_id))) {
|
2018-09-21 04:27:50 +03:00
|
|
|
PipelineTexturesHolder* holder = entry.Data();
|
|
|
|
if (holder->mDestroyedEpoch.isSome()) {
|
2018-11-05 12:58:37 +03:00
|
|
|
while (!holder->mTextureHosts.empty()) {
|
|
|
|
// Need to extend holding TextureHost if it is direct bounded texture.
|
|
|
|
HoldUntilNotUsedByGPU(holder->mTextureHosts.front().mTexture,
|
|
|
|
aUpdatesCount);
|
|
|
|
holder->mTextureHosts.pop();
|
|
|
|
}
|
2018-02-12 19:43:08 +03:00
|
|
|
// Remove Pipeline
|
|
|
|
entry.Remove();
|
|
|
|
}
|
|
|
|
// If mDestroyedEpoch contains nothing it means we reused the same pipeline
|
|
|
|
// id (probably because we moved the tab to another window). In this case we
|
|
|
|
// need to keep the holder.
|
2018-02-12 19:37:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 12:58:37 +03:00
|
|
|
void AsyncImagePipelineManager::HoldUntilNotUsedByGPU(
|
|
|
|
const CompositableTextureHostRef& aTextureHost, uint64_t aUpdatesCount) {
|
|
|
|
MOZ_ASSERT(aTextureHost);
|
|
|
|
|
|
|
|
if (aTextureHost->HasIntermediateBuffer()) {
|
|
|
|
// If texutre is not direct binding texture, gpu has already finished using
|
|
|
|
// it. We could release it now.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// When Triple buffer is used, we need wait one more WebRender rendering,
|
|
|
|
if (mUseTripleBuffering) {
|
|
|
|
++aUpdatesCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
mTexturesInUseByGPU.emplace(std::make_pair(aUpdatesCount, aTextureHost));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsyncImagePipelineManager::CheckForTextureHostsNotUsedByGPU() {
|
|
|
|
uint64_t currCount = mUpdatesCount;
|
|
|
|
|
|
|
|
while (!mTexturesInUseByGPU.empty()) {
|
|
|
|
if (currCount <= mTexturesInUseByGPU.front().first) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mTexturesInUseByGPU.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 19:29:56 +03:00
|
|
|
wr::Epoch AsyncImagePipelineManager::GetNextImageEpoch() {
|
|
|
|
mAsyncImageEpoch.mHandle++;
|
|
|
|
return mAsyncImageEpoch;
|
|
|
|
}
|
|
|
|
|
2017-01-20 05:26:13 +03:00
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|