зеркало из https://github.com/mozilla/gecko-dev.git
651 строка
21 KiB
C++
651 строка
21 KiB
C++
/* -*- 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
|
|
* 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/. */
|
|
|
|
#include "mozilla/layers/WebRenderBridgeChild.h"
|
|
|
|
#include "gfxPlatform.h"
|
|
#include "mozilla/StaticPrefs_gfx.h"
|
|
#include "mozilla/dom/TabGroup.h"
|
|
#include "mozilla/layers/CompositableClient.h"
|
|
#include "mozilla/layers/CompositorBridgeChild.h"
|
|
#include "mozilla/layers/ImageDataSerializer.h"
|
|
#include "mozilla/layers/IpcResourceUpdateQueue.h"
|
|
#include "mozilla/layers/StackingContextHelper.h"
|
|
#include "mozilla/layers/PTextureChild.h"
|
|
#include "mozilla/layers/WebRenderLayerManager.h"
|
|
#include "mozilla/webrender/WebRenderAPI.h"
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
|
|
: mIsInTransaction(false),
|
|
mIsInClearCachedResources(false),
|
|
mIdNamespace{0},
|
|
mResourceId(0),
|
|
mPipelineId(aPipelineId),
|
|
mManager(nullptr),
|
|
mIPCOpen(false),
|
|
mDestroyed(false),
|
|
mSentDisplayList(false),
|
|
mFontKeysDeleted(),
|
|
mFontInstanceKeysDeleted() {}
|
|
|
|
WebRenderBridgeChild::~WebRenderBridgeChild() {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
MOZ_ASSERT(mDestroyed);
|
|
}
|
|
|
|
void WebRenderBridgeChild::Destroy(bool aIsSync) {
|
|
if (!IPCOpen()) {
|
|
return;
|
|
}
|
|
|
|
DoDestroy();
|
|
|
|
if (aIsSync) {
|
|
SendShutdownSync();
|
|
} else {
|
|
SendShutdown();
|
|
}
|
|
}
|
|
|
|
void WebRenderBridgeChild::ActorDestroy(ActorDestroyReason why) { DoDestroy(); }
|
|
|
|
void WebRenderBridgeChild::DoDestroy() {
|
|
if (RefCountedShm::IsValid(mResourceShm) &&
|
|
RefCountedShm::Release(mResourceShm) == 0) {
|
|
RefCountedShm::Dealloc(this, mResourceShm);
|
|
mResourceShm = RefCountedShmem();
|
|
}
|
|
|
|
// mDestroyed is used to prevent calling Send__delete__() twice.
|
|
// When this function is called from CompositorBridgeChild::Destroy().
|
|
// mActiveResourceTracker is not cleared here, since it is
|
|
// used by PersistentBufferProviderShared.
|
|
mDestroyed = true;
|
|
mManager = nullptr;
|
|
}
|
|
|
|
void WebRenderBridgeChild::AddWebRenderParentCommand(
|
|
const WebRenderParentCommand& aCmd, wr::RenderRoot aRenderRoot) {
|
|
MOZ_ASSERT(aRenderRoot == wr::RenderRoot::Default ||
|
|
(XRE_IsParentProcess() &&
|
|
StaticPrefs::gfx_webrender_split_render_roots_AtStartup()));
|
|
mParentCommands[aRenderRoot].AppendElement(aCmd);
|
|
}
|
|
|
|
void WebRenderBridgeChild::BeginTransaction() {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
|
|
UpdateFwdTransactionId();
|
|
mIsInTransaction = true;
|
|
}
|
|
|
|
void WebRenderBridgeChild::UpdateResources(
|
|
wr::IpcResourceUpdateQueue& aResources, wr::RenderRoot aRenderRoot) {
|
|
if (!IPCOpen()) {
|
|
aResources.Clear();
|
|
return;
|
|
}
|
|
|
|
if (aResources.IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
nsTArray<OpUpdateResource> resourceUpdates;
|
|
nsTArray<RefCountedShmem> smallShmems;
|
|
nsTArray<ipc::Shmem> largeShmems;
|
|
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
|
|
|
this->SendUpdateResources(resourceUpdates, smallShmems,
|
|
std::move(largeShmems), aRenderRoot);
|
|
}
|
|
|
|
void WebRenderBridgeChild::EndTransaction(
|
|
nsTArray<RenderRootDisplayListData>& aRenderRoots,
|
|
TransactionId aTransactionId, bool aContainsSVGGroup,
|
|
const mozilla::VsyncId& aVsyncId, const mozilla::TimeStamp& aVsyncStartTime,
|
|
const mozilla::TimeStamp& aRefreshStartTime,
|
|
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
MOZ_ASSERT(mIsInTransaction);
|
|
|
|
TimeStamp fwdTime = TimeStamp::Now();
|
|
|
|
for (auto& renderRoot : aRenderRoots) {
|
|
MOZ_ASSERT(renderRoot.mRenderRoot == wr::RenderRoot::Default ||
|
|
(XRE_IsParentProcess() &&
|
|
StaticPrefs::gfx_webrender_split_render_roots_AtStartup()));
|
|
renderRoot.mCommands = std::move(mParentCommands[renderRoot.mRenderRoot]);
|
|
renderRoot.mIdNamespace = mIdNamespace;
|
|
}
|
|
|
|
nsTArray<CompositionPayload> payloads;
|
|
if (mManager) {
|
|
mManager->TakeCompositionPayloads(payloads);
|
|
}
|
|
|
|
mSentDisplayList = true;
|
|
this->SendSetDisplayList(
|
|
std::move(aRenderRoots), mDestroyedActors, GetFwdTransactionId(),
|
|
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
|
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
|
|
|
|
// With multiple render roots, we may not have sent all of our
|
|
// mParentCommands, so go ahead and go through our mParentCommands and ensure
|
|
// they get sent.
|
|
ProcessWebRenderParentCommands();
|
|
mDestroyedActors.Clear();
|
|
mIsInTransaction = false;
|
|
}
|
|
|
|
void WebRenderBridgeChild::EndEmptyTransaction(
|
|
const FocusTarget& aFocusTarget,
|
|
nsTArray<RenderRootUpdates>& aRenderRootUpdates,
|
|
TransactionId aTransactionId, const mozilla::VsyncId& aVsyncId,
|
|
const mozilla::TimeStamp& aVsyncStartTime,
|
|
const mozilla::TimeStamp& aRefreshStartTime,
|
|
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
MOZ_ASSERT(mIsInTransaction);
|
|
|
|
TimeStamp fwdTime = TimeStamp::Now();
|
|
|
|
for (auto& update : aRenderRootUpdates) {
|
|
MOZ_ASSERT(update.mRenderRoot == wr::RenderRoot::Default ||
|
|
(XRE_IsParentProcess() &&
|
|
StaticPrefs::gfx_webrender_split_render_roots_AtStartup()));
|
|
update.mCommands = std::move(mParentCommands[update.mRenderRoot]);
|
|
}
|
|
|
|
nsTArray<CompositionPayload> payloads;
|
|
if (mManager) {
|
|
mManager->TakeCompositionPayloads(payloads);
|
|
}
|
|
|
|
this->SendEmptyTransaction(
|
|
aFocusTarget, std::move(aRenderRootUpdates), mDestroyedActors,
|
|
GetFwdTransactionId(), aTransactionId, aVsyncId, aVsyncStartTime,
|
|
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
|
|
|
|
// With multiple render roots, we may not have sent all of our
|
|
// mParentCommands, so go ahead and go through our mParentCommands and ensure
|
|
// they get sent.
|
|
ProcessWebRenderParentCommands();
|
|
mDestroyedActors.Clear();
|
|
mIsInTransaction = false;
|
|
}
|
|
|
|
void WebRenderBridgeChild::ProcessWebRenderParentCommands() {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
|
|
for (auto renderRoot : wr::kRenderRoots) {
|
|
if (!mParentCommands[renderRoot].IsEmpty()) {
|
|
MOZ_ASSERT(renderRoot == wr::RenderRoot::Default ||
|
|
StaticPrefs::gfx_webrender_split_render_roots_AtStartup());
|
|
this->SendParentCommands(mParentCommands[renderRoot], renderRoot);
|
|
mParentCommands[renderRoot].Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
void WebRenderBridgeChild::AddPipelineIdForAsyncCompositable(
|
|
const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle,
|
|
wr::RenderRoot aRenderRoot) {
|
|
AddWebRenderParentCommand(
|
|
OpAddPipelineIdForCompositable(aPipelineId, aHandle, /* isAsync */ true),
|
|
aRenderRoot);
|
|
}
|
|
|
|
void WebRenderBridgeChild::AddPipelineIdForCompositable(
|
|
const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle,
|
|
wr::RenderRoot aRenderRoot) {
|
|
AddWebRenderParentCommand(
|
|
OpAddPipelineIdForCompositable(aPipelineId, aHandle, /* isAsync */ false),
|
|
aRenderRoot);
|
|
}
|
|
|
|
void WebRenderBridgeChild::RemovePipelineIdForCompositable(
|
|
const wr::PipelineId& aPipelineId, wr::RenderRoot aRenderRoot) {
|
|
AddWebRenderParentCommand(OpRemovePipelineIdForCompositable(aPipelineId),
|
|
aRenderRoot);
|
|
}
|
|
|
|
wr::ExternalImageId WebRenderBridgeChild::GetNextExternalImageId() {
|
|
wr::MaybeExternalImageId id =
|
|
GetCompositorBridgeChild()->GetNextExternalImageId();
|
|
MOZ_RELEASE_ASSERT(id.isSome());
|
|
return id.value();
|
|
}
|
|
|
|
void WebRenderBridgeChild::ReleaseTextureOfImage(const wr::ImageKey& aKey,
|
|
wr::RenderRoot aRenderRoot) {
|
|
AddWebRenderParentCommand(OpReleaseTextureOfImage(aKey), aRenderRoot);
|
|
}
|
|
|
|
struct FontFileDataSink {
|
|
wr::FontKey* mFontKey;
|
|
WebRenderBridgeChild* mWrBridge;
|
|
wr::IpcResourceUpdateQueue* mResources;
|
|
};
|
|
|
|
static void WriteFontFileData(const uint8_t* aData, uint32_t aLength,
|
|
uint32_t aIndex, void* aBaton) {
|
|
FontFileDataSink* sink = static_cast<FontFileDataSink*>(aBaton);
|
|
|
|
*sink->mFontKey = sink->mWrBridge->GetNextFontKey();
|
|
|
|
sink->mResources->AddRawFont(
|
|
*sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength),
|
|
aIndex);
|
|
}
|
|
|
|
static void WriteFontDescriptor(const uint8_t* aData, uint32_t aLength,
|
|
uint32_t aIndex, void* aBaton) {
|
|
FontFileDataSink* sink = static_cast<FontFileDataSink*>(aBaton);
|
|
|
|
*sink->mFontKey = sink->mWrBridge->GetNextFontKey();
|
|
|
|
sink->mResources->AddFontDescriptor(
|
|
*sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength),
|
|
aIndex);
|
|
}
|
|
|
|
void WebRenderBridgeChild::PushGlyphs(
|
|
wr::DisplayListBuilder& aBuilder, Range<const wr::GlyphInstance> aGlyphs,
|
|
gfx::ScaledFont* aFont, const wr::ColorF& aColor,
|
|
const StackingContextHelper& aSc, const wr::LayoutRect& aBounds,
|
|
const wr::LayoutRect& aClip, bool aBackfaceVisible,
|
|
const wr::GlyphOptions* aGlyphOptions) {
|
|
MOZ_ASSERT(aFont);
|
|
|
|
Maybe<wr::WrFontInstanceKey> key =
|
|
GetFontKeyForScaledFont(aFont, aBuilder.GetRenderRoot());
|
|
MOZ_ASSERT(key.isSome());
|
|
|
|
if (key.isSome()) {
|
|
aBuilder.PushText(aBounds, aClip, aBackfaceVisible, aColor, key.value(),
|
|
aGlyphs, aGlyphOptions);
|
|
}
|
|
}
|
|
|
|
Maybe<wr::FontInstanceKey> WebRenderBridgeChild::GetFontKeyForScaledFont(
|
|
gfx::ScaledFont* aScaledFont, wr::RenderRoot aRenderRoot,
|
|
wr::IpcResourceUpdateQueue* aResources) {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
MOZ_ASSERT(aScaledFont);
|
|
MOZ_ASSERT(aScaledFont->CanSerialize());
|
|
|
|
auto& fontInstanceKeys = mFontInstanceKeys[aRenderRoot];
|
|
wr::FontInstanceKey instanceKey = {wr::IdNamespace{0}, 0};
|
|
if (fontInstanceKeys.Get(aScaledFont, &instanceKey)) {
|
|
return Some(instanceKey);
|
|
}
|
|
|
|
Maybe<wr::IpcResourceUpdateQueue> resources =
|
|
aResources ? Nothing() : Some(wr::IpcResourceUpdateQueue(this));
|
|
aResources = resources.ptrOr(aResources);
|
|
|
|
Maybe<wr::FontKey> fontKey = GetFontKeyForUnscaledFont(
|
|
aScaledFont->GetUnscaledFont(), aRenderRoot, aResources);
|
|
if (fontKey.isNothing()) {
|
|
return Nothing();
|
|
}
|
|
|
|
instanceKey = GetNextFontInstanceKey();
|
|
|
|
Maybe<wr::FontInstanceOptions> options;
|
|
Maybe<wr::FontInstancePlatformOptions> platformOptions;
|
|
std::vector<FontVariation> variations;
|
|
aScaledFont->GetWRFontInstanceOptions(&options, &platformOptions,
|
|
&variations);
|
|
|
|
aResources->AddFontInstance(
|
|
instanceKey, fontKey.value(), aScaledFont->GetSize(),
|
|
options.ptrOr(nullptr), platformOptions.ptrOr(nullptr),
|
|
Range<const FontVariation>(variations.data(), variations.size()));
|
|
if (resources.isSome()) {
|
|
UpdateResources(resources.ref(), aRenderRoot);
|
|
}
|
|
|
|
fontInstanceKeys.Put(aScaledFont, instanceKey);
|
|
|
|
return Some(instanceKey);
|
|
}
|
|
|
|
Maybe<wr::FontKey> WebRenderBridgeChild::GetFontKeyForUnscaledFont(
|
|
gfx::UnscaledFont* aUnscaled, wr::RenderRoot aRenderRoot,
|
|
wr::IpcResourceUpdateQueue* aResources) {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
|
|
auto& fontKeys = mFontKeys[aRenderRoot];
|
|
wr::FontKey fontKey = {wr::IdNamespace{0}, 0};
|
|
if (!fontKeys.Get(aUnscaled, &fontKey)) {
|
|
Maybe<wr::IpcResourceUpdateQueue> resources =
|
|
aResources ? Nothing() : Some(wr::IpcResourceUpdateQueue(this));
|
|
|
|
FontFileDataSink sink = {&fontKey, this, resources.ptrOr(aResources)};
|
|
// First try to retrieve a descriptor for the font, as this is much cheaper
|
|
// to send over IPC than the full raw font data. If this is not possible,
|
|
// then and only then fall back to getting the raw font file data. If that
|
|
// fails, then the only thing left to do is signal failure by returning a
|
|
// null font key.
|
|
if (!aUnscaled->GetWRFontDescriptor(WriteFontDescriptor, &sink) &&
|
|
!aUnscaled->GetFontFileData(WriteFontFileData, &sink)) {
|
|
return Nothing();
|
|
}
|
|
|
|
if (resources.isSome()) {
|
|
UpdateResources(resources.ref(), aRenderRoot);
|
|
}
|
|
|
|
fontKeys.Put(aUnscaled, fontKey);
|
|
}
|
|
|
|
return Some(fontKey);
|
|
}
|
|
|
|
void WebRenderBridgeChild::RemoveExpiredFontKeys(
|
|
wr::IpcResourceUpdateQueue& aResourceUpdates) {
|
|
auto& fontInstanceKeys = mFontInstanceKeys[aResourceUpdates.GetRenderRoot()];
|
|
auto& fontKeys = mFontKeys[aResourceUpdates.GetRenderRoot()];
|
|
auto& fontInstanceKeysDeleted =
|
|
mFontInstanceKeysDeleted[aResourceUpdates.GetRenderRoot()];
|
|
auto& fontKeysDeleted = mFontKeysDeleted[aResourceUpdates.GetRenderRoot()];
|
|
|
|
uint32_t counter = gfx::ScaledFont::DeletionCounter();
|
|
if (fontInstanceKeysDeleted != counter) {
|
|
fontInstanceKeysDeleted = counter;
|
|
for (auto iter = fontInstanceKeys.Iter(); !iter.Done(); iter.Next()) {
|
|
if (!iter.Key()) {
|
|
aResourceUpdates.DeleteFontInstance(iter.Data());
|
|
iter.Remove();
|
|
}
|
|
}
|
|
}
|
|
counter = gfx::UnscaledFont::DeletionCounter();
|
|
if (fontKeysDeleted != counter) {
|
|
fontKeysDeleted = counter;
|
|
for (auto iter = fontKeys.Iter(); !iter.Done(); iter.Next()) {
|
|
if (!iter.Key()) {
|
|
aResourceUpdates.DeleteFont(iter.Data());
|
|
iter.Remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CompositorBridgeChild* WebRenderBridgeChild::GetCompositorBridgeChild() {
|
|
if (!IPCOpen()) {
|
|
return nullptr;
|
|
}
|
|
return static_cast<CompositorBridgeChild*>(Manager());
|
|
}
|
|
|
|
TextureForwarder* WebRenderBridgeChild::GetTextureForwarder() {
|
|
return static_cast<TextureForwarder*>(GetCompositorBridgeChild());
|
|
}
|
|
|
|
LayersIPCActor* WebRenderBridgeChild::GetLayersIPCActor() {
|
|
return static_cast<LayersIPCActor*>(GetCompositorBridgeChild());
|
|
}
|
|
|
|
void WebRenderBridgeChild::SyncWithCompositor() {
|
|
if (!IPCOpen()) {
|
|
return;
|
|
}
|
|
SendSyncWithCompositor();
|
|
}
|
|
|
|
void WebRenderBridgeChild::Connect(CompositableClient* aCompositable,
|
|
ImageContainer* aImageContainer) {
|
|
MOZ_ASSERT(!mDestroyed);
|
|
MOZ_ASSERT(aCompositable);
|
|
|
|
static uint64_t sNextID = 1;
|
|
uint64_t id = sNextID++;
|
|
|
|
mCompositables.Put(id, aCompositable);
|
|
|
|
CompositableHandle handle(id);
|
|
aCompositable->InitIPDL(handle);
|
|
SendNewCompositable(handle, aCompositable->GetTextureInfo());
|
|
}
|
|
|
|
void WebRenderBridgeChild::UseTiledLayerBuffer(
|
|
CompositableClient* aCompositable,
|
|
const SurfaceDescriptorTiles& aTiledDescriptor) {}
|
|
|
|
void WebRenderBridgeChild::UpdateTextureRegion(
|
|
CompositableClient* aCompositable,
|
|
const ThebesBufferData& aThebesBufferData,
|
|
const nsIntRegion& aUpdatedRegion) {}
|
|
|
|
bool WebRenderBridgeChild::AddOpDestroy(const OpDestroy& aOp) {
|
|
if (!mIsInTransaction) {
|
|
return false;
|
|
}
|
|
|
|
mDestroyedActors.AppendElement(aOp);
|
|
return true;
|
|
}
|
|
|
|
void WebRenderBridgeChild::ReleaseCompositable(
|
|
const CompositableHandle& aHandle) {
|
|
if (!IPCOpen()) {
|
|
// This can happen if the IPC connection was torn down, because, e.g.
|
|
// the GPU process died.
|
|
return;
|
|
}
|
|
if (!DestroyInTransaction(aHandle)) {
|
|
SendReleaseCompositable(aHandle);
|
|
}
|
|
mCompositables.Remove(aHandle.Value());
|
|
}
|
|
|
|
bool WebRenderBridgeChild::DestroyInTransaction(PTextureChild* aTexture) {
|
|
return AddOpDestroy(OpDestroy(aTexture));
|
|
}
|
|
|
|
bool WebRenderBridgeChild::DestroyInTransaction(
|
|
const CompositableHandle& aHandle) {
|
|
return AddOpDestroy(OpDestroy(aHandle));
|
|
}
|
|
|
|
void WebRenderBridgeChild::RemoveTextureFromCompositable(
|
|
CompositableClient* aCompositable, TextureClient* aTexture,
|
|
const Maybe<wr::RenderRoot>& aRenderRoot) {
|
|
MOZ_ASSERT(aCompositable);
|
|
MOZ_ASSERT(aTexture);
|
|
MOZ_ASSERT(aTexture->GetIPDLActor());
|
|
MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() ==
|
|
GetIPCChannel());
|
|
if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
|
|
// We don't have an actor anymore, don't try to use it!
|
|
return;
|
|
}
|
|
|
|
AddWebRenderParentCommand(
|
|
CompositableOperation(aCompositable->GetIPCHandle(),
|
|
OpRemoveTexture(nullptr, aTexture->GetIPDLActor())),
|
|
*aRenderRoot);
|
|
}
|
|
|
|
void WebRenderBridgeChild::UseTextures(
|
|
CompositableClient* aCompositable,
|
|
const nsTArray<TimedTextureClient>& aTextures,
|
|
const Maybe<wr::RenderRoot>& aRenderRoot) {
|
|
MOZ_ASSERT(aCompositable);
|
|
|
|
if (!aCompositable->IsConnected()) {
|
|
return;
|
|
}
|
|
|
|
AutoTArray<TimedTexture, 4> textures;
|
|
|
|
for (auto& t : aTextures) {
|
|
MOZ_ASSERT(t.mTextureClient);
|
|
MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
|
|
MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() ==
|
|
GetIPCChannel());
|
|
bool readLocked = t.mTextureClient->OnForwardedToHost();
|
|
|
|
textures.AppendElement(
|
|
TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(), t.mTimeStamp,
|
|
t.mPictureRect, t.mFrameID, t.mProducerID, readLocked));
|
|
GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(
|
|
t.mTextureClient);
|
|
}
|
|
AddWebRenderParentCommand(CompositableOperation(aCompositable->GetIPCHandle(),
|
|
OpUseTexture(textures)),
|
|
*aRenderRoot);
|
|
}
|
|
|
|
void WebRenderBridgeChild::UseComponentAlphaTextures(
|
|
CompositableClient* aCompositable, TextureClient* aClientOnBlack,
|
|
TextureClient* aClientOnWhite) {}
|
|
|
|
void WebRenderBridgeChild::UpdateFwdTransactionId() {
|
|
GetCompositorBridgeChild()->UpdateFwdTransactionId();
|
|
}
|
|
|
|
uint64_t WebRenderBridgeChild::GetFwdTransactionId() {
|
|
return GetCompositorBridgeChild()->GetFwdTransactionId();
|
|
}
|
|
|
|
bool WebRenderBridgeChild::InForwarderThread() { return NS_IsMainThread(); }
|
|
|
|
mozilla::ipc::IPCResult WebRenderBridgeChild::RecvWrUpdated(
|
|
const wr::IdNamespace& aNewIdNamespace,
|
|
const TextureFactoryIdentifier& textureFactoryIdentifier) {
|
|
if (mManager) {
|
|
mManager->WrUpdated();
|
|
}
|
|
IdentifyTextureHost(textureFactoryIdentifier);
|
|
// Update mIdNamespace to identify obsolete keys and messages by
|
|
// WebRenderBridgeParent. Since usage of invalid keys could cause crash in
|
|
// webrender.
|
|
mIdNamespace = aNewIdNamespace;
|
|
// Just clear FontInstaceKeys/FontKeys, they are removed during WebRenderAPI
|
|
// destruction.
|
|
for (auto renderRoot : wr::kRenderRoots) {
|
|
mFontInstanceKeys[renderRoot].Clear();
|
|
mFontKeys[renderRoot].Clear();
|
|
}
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult WebRenderBridgeChild::RecvWrReleasedImages(
|
|
nsTArray<wr::ExternalImageKeyPair>&& aPairs) {
|
|
if (mManager) {
|
|
mManager->WrReleasedImages(aPairs);
|
|
}
|
|
return IPC_OK();
|
|
}
|
|
|
|
void WebRenderBridgeChild::BeginClearCachedResources() {
|
|
mSentDisplayList = false;
|
|
mIsInClearCachedResources = true;
|
|
// Clear display list and animtaions at parent side before clearing cached
|
|
// resources on client side. It prevents to clear resources before clearing
|
|
// display list at parent side.
|
|
SendClearCachedResources();
|
|
}
|
|
|
|
void WebRenderBridgeChild::EndClearCachedResources() {
|
|
if (!IPCOpen()) {
|
|
mIsInClearCachedResources = false;
|
|
return;
|
|
}
|
|
ProcessWebRenderParentCommands();
|
|
mIsInClearCachedResources = false;
|
|
}
|
|
|
|
void WebRenderBridgeChild::SetWebRenderLayerManager(
|
|
WebRenderLayerManager* aManager) {
|
|
MOZ_ASSERT(aManager && !mManager);
|
|
mManager = aManager;
|
|
|
|
nsCOMPtr<nsIEventTarget> eventTarget = nullptr;
|
|
if (dom::TabGroup* tabGroup = mManager->GetTabGroup()) {
|
|
eventTarget = tabGroup->EventTargetFor(TaskCategory::Other);
|
|
}
|
|
MOZ_ASSERT(eventTarget || !XRE_IsContentProcess());
|
|
mActiveResourceTracker = MakeUnique<ActiveResourceTracker>(
|
|
1000, "CompositableForwarder", eventTarget);
|
|
}
|
|
|
|
ipc::IShmemAllocator* WebRenderBridgeChild::GetShmemAllocator() {
|
|
if (!IPCOpen()) {
|
|
return nullptr;
|
|
}
|
|
return static_cast<CompositorBridgeChild*>(Manager());
|
|
}
|
|
|
|
RefPtr<KnowsCompositor> WebRenderBridgeChild::GetForMedia() {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
// Ensure devices initialization for video playback. The devices are lazily
|
|
// initialized with WebRender to reduce memory usage.
|
|
gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
|
|
|
|
return MakeAndAddRef<KnowsCompositorMediaProxy>(
|
|
GetTextureFactoryIdentifier());
|
|
}
|
|
|
|
bool WebRenderBridgeChild::AllocResourceShmem(size_t aSize,
|
|
RefCountedShmem& aShm) {
|
|
// We keep a single shmem around to reuse later if it is reference count has
|
|
// dropped back to 1 (the reference held by the WebRenderBridgeChild).
|
|
|
|
// If the cached shmem exists, has the correct size and isn't held by anything
|
|
// other than us, recycle it.
|
|
bool alreadyAllocated = RefCountedShm::IsValid(mResourceShm);
|
|
if (alreadyAllocated) {
|
|
if (RefCountedShm::GetSize(mResourceShm) == aSize &&
|
|
RefCountedShm::GetReferenceCount(mResourceShm) <= 1) {
|
|
MOZ_ASSERT(RefCountedShm::GetReferenceCount(mResourceShm) == 1);
|
|
aShm = mResourceShm;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// If there was no cached shmem or we couldn't recycle it, alloc a new one.
|
|
if (!RefCountedShm::Alloc(this, aSize, aShm)) {
|
|
return false;
|
|
}
|
|
|
|
// Now that we have a valid shmem, put it in the cache if we don't have one
|
|
// yet.
|
|
if (!alreadyAllocated) {
|
|
mResourceShm = aShm;
|
|
RefCountedShm::AddRef(aShm);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WebRenderBridgeChild::DeallocResourceShmem(RefCountedShmem& aShm) {
|
|
if (!RefCountedShm::IsValid(aShm)) {
|
|
return;
|
|
}
|
|
MOZ_ASSERT(RefCountedShm::GetReferenceCount(aShm) == 0);
|
|
|
|
RefCountedShm::Dealloc(this, aShm);
|
|
}
|
|
|
|
void WebRenderBridgeChild::Capture() { this->SendCapture(); }
|
|
|
|
void WebRenderBridgeChild::SetTransactionLogging(bool aValue) {
|
|
this->SendSetTransactionLogging(aValue);
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|