Bug 1322086 - Handle texture recycling in WebRenderImageLayer r=nical?

This commit is contained in:
Sotaro Ikeda 2016-12-07 02:02:04 -08:00
Родитель 7383fcbb4a
Коммит e0f89688a5
5 изменённых файлов: 104 добавлений и 54 удалений

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

@ -38,8 +38,8 @@ parent:
sync DeleteImage(WRImageKey aImageKey);
sync DPBegin(uint32_t aWidth, uint32_t aHeight)
returns (bool aOutSuccess);
async DPEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t transactionId);
sync DPSyncEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t transactionId);
async DPEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
sync DPSyncEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
sync DPGetSnapshot(PTexture texture, IntRect dirtyRect);
async AddExternalImageId(uint64_t aImageId, uint64_t aAsyncContainerId);
async RemoveExternalImageId(uint64_t aImageId);

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

@ -55,6 +55,7 @@ WebRenderBridgeChild::DPBegin(uint32_t aWidth, uint32_t aHeight)
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(!mIsInTransaction);
bool success = false;
UpdateFwdTransactionId();
this->SendDPBegin(aWidth, aHeight, &success);
if (!success) {
return false;
@ -70,9 +71,9 @@ WebRenderBridgeChild::DPEnd(bool aIsSync, uint64_t aTransactionId)
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(mIsInTransaction);
if (aIsSync) {
this->SendDPSyncEnd(mCommands, mDestroyedActors, aTransactionId);
this->SendDPSyncEnd(mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
} else {
this->SendDPEnd(mCommands, mDestroyedActors, aTransactionId);
this->SendDPEnd(mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
}
mCommands.Clear();
@ -248,8 +249,7 @@ WebRenderBridgeChild::UseTextures(CompositableClient* aCompositable,
MarkSyncTransaction();
}
// XXX Enable recycle
//mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
}
AddWebRenderCommand(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
OpUseTexture(textures)));
@ -266,13 +266,13 @@ WebRenderBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositabl
void
WebRenderBridgeChild::UpdateFwdTransactionId()
{
GetCompositorBridgeChild()->UpdateFwdTransactionId();
}
uint64_t
WebRenderBridgeChild::GetFwdTransactionId()
{
return 0;
return GetCompositorBridgeChild()->GetFwdTransactionId();
}
bool

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

@ -28,6 +28,33 @@ namespace layers {
using namespace mozilla::gfx;
class MOZ_STACK_CLASS AutoWebRenderBridgeParentAsyncMessageSender
{
public:
explicit AutoWebRenderBridgeParentAsyncMessageSender(WebRenderBridgeParent* aWebRenderBridgeParent,
InfallibleTArray<OpDestroy>* aDestroyActors = nullptr)
: mWebRenderBridgeParent(aWebRenderBridgeParent)
, mActorsToDestroy(aDestroyActors)
{
mWebRenderBridgeParent->SetAboutToSendAsyncMessages();
}
~AutoWebRenderBridgeParentAsyncMessageSender()
{
mWebRenderBridgeParent->SendPendingAsyncMessages();
if (mActorsToDestroy) {
// Destroy the actors after sending the async messages because the latter may contain
// references to some actors.
for (const auto& op : *mActorsToDestroy) {
mWebRenderBridgeParent->DestroyActor(op);
}
}
}
private:
WebRenderBridgeParent* mWebRenderBridgeParent;
InfallibleTArray<OpDestroy>* mActorsToDestroy;
};
WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
const uint64_t& aPipelineId,
widget::CompositorWidget* aWidget,
@ -167,14 +194,21 @@ WebRenderBridgeParent::RecvDPBegin(const uint32_t& aWidth,
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId)
{
UpdateFwdTransactionId(aFwdTransactionId);
if (mDestroyed) {
for (const auto& op : aToDestroy) {
DestroyActor(op);
}
return IPC_OK();
}
// This ensures that destroy operations are always processed. It is not safe
// to early-return from RecvDPEnd without doing so.
AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
ProcessWebrenderCommands(aCommands);
// The transaction ID might get reset to 1 if the page gets reloaded, see
@ -182,24 +216,27 @@ WebRenderBridgeParent::RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
// Otherwise, it should be continually increasing.
MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransactionId);
mPendingTransactionId = aTransactionId;
for (const auto& op : aToDestroy) {
DestroyActor(op);
}
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId)
{
UpdateFwdTransactionId(aFwdTransactionId);
if (mDestroyed) {
for (const auto& op : aToDestroy) {
DestroyActor(op);
}
return IPC_OK();
}
// This ensures that destroy operations are always processed. It is not safe
// to early-return from RecvDPEnd without doing so.
AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
ProcessWebrenderCommands(aCommands);
// The transaction ID might get reset to 1 if the page gets reloaded, see
@ -207,10 +244,6 @@ WebRenderBridgeParent::RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aComma
// Otherwise, it should be continually increasing.
MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransactionId);
mPendingTransactionId = aTransactionId;
for (const auto& op : aToDestroy) {
DestroyActor(op);
}
return IPC_OK();
}
@ -498,6 +531,20 @@ WebRenderBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessag
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
void
WebRenderBridgeParent::SendPendingAsyncMessages()
{
MOZ_ASSERT(mCompositorBridge);
mCompositorBridge->SendPendingAsyncMessages();
}
void
WebRenderBridgeParent::SetAboutToSendAsyncMessages()
{
MOZ_ASSERT(mCompositorBridge);
mCompositorBridge->SetAboutToSendAsyncMessages();
}
void
WebRenderBridgeParent::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
{

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

@ -66,9 +66,11 @@ public:
bool* aOutSuccess) override;
mozilla::ipc::IPCResult RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId) override;
mozilla::ipc::IPCResult RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId) override;
mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture,
const gfx::IntRect& aRect) override;
@ -94,17 +96,19 @@ public:
void FinishPendingComposite() override { }
void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr) override;
private:
virtual ~WebRenderBridgeParent();
virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) override;
bool DeallocPCompositableParent(PCompositableParent* aActor) override;
// CompositableParentManager
bool IsSameProcess() const override;
base::ProcessId GetChildProcessId() override;
void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
void SendPendingAsyncMessages() override;
void SetAboutToSendAsyncMessages() override;
private:
virtual ~WebRenderBridgeParent();
virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) override;
bool DeallocPCompositableParent(PCompositableParent* aActor) override;
void DeleteOldImages();
void ProcessWebrenderCommands(InfallibleTArray<WebRenderCommand>& commands);

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

@ -7,6 +7,7 @@
#include "LayersLogging.h"
#include "mozilla/layers/ImageClient.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
#include "mozilla/layers/TextureWrapperImage.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
@ -59,41 +60,9 @@ WebRenderImageLayer::RenderLayer()
return;
}
gfx::IntSize size = surface->GetSize();
// XXX Add external image id handling
// XXX Add texure recycling
// XXX Add other TextureData supports.
// Only BufferTexture is supported now.
RefPtr<TextureClient> texture =
TextureClient::CreateForRawBufferAccess(WRBridge(),
surface->GetFormat(),
size,
BackendType::SKIA,
TextureFlags::DEFAULT);
if (!texture) {
return;
}
MOZ_ASSERT(texture->CanExposeDrawTarget());
TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
return;
}
RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
if (!drawTarget || !drawTarget->IsValid()) {
return;
}
drawTarget->CopySurface(surface, IntRect(IntPoint(), size), IntPoint());
if (!mImageContainerForWR) {
mImageContainerForWR = LayerManager::CreateImageContainer();
}
RefPtr<TextureWrapperImage> image =
new TextureWrapperImage(texture, IntRect(IntPoint(0, 0), size));
mImageContainerForWR->SetCurrentImageInTransaction(image);
if (!mImageClient) {
mImageClient = ImageClient::CreateImageClient(CompositableType::IMAGE,
@ -105,6 +74,36 @@ WebRenderImageLayer::RenderLayer()
mImageClient->Connect();
}
gfx::IntSize size = surface->GetSize();
// XXX Add external image id handling
RefPtr<TextureClient> texture = mImageClient->GetTextureClientRecycler()
->CreateOrRecycle(surface->GetFormat(),
size,
BackendSelector::Content,
TextureFlags::DEFAULT);
if (!texture) {
return;
}
MOZ_ASSERT(texture->CanExposeDrawTarget());
{
TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
return;
}
RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
if (!drawTarget || !drawTarget->IsValid()) {
return;
}
drawTarget->CopySurface(surface, IntRect(IntPoint(), size), IntPoint());
}
RefPtr<TextureWrapperImage> image =
new TextureWrapperImage(texture, IntRect(IntPoint(0, 0), size));
mImageContainerForWR->SetCurrentImageInTransaction(image);
if (!mImageClient->UpdateImage(mImageContainerForWR, /* unused */0)) {
return;
}