Bug 1318113 - Use BufferTexture to return the reftest snapshot r=nical?

This commit is contained in:
sotaro 2016-11-28 11:39:42 +09:00
parent 0a3554cf97
commit 753708476e
14 changed files with 141 additions and 31 deletions

View File

@ -1156,7 +1156,7 @@ CompositorBridgeChild::HandleFatalError(const char* aName, const char* aMsg) con
}
PWebRenderBridgeChild*
CompositorBridgeChild::AllocPWebRenderBridgeChild(const uint64_t& aPipelineId)
CompositorBridgeChild::AllocPWebRenderBridgeChild(const uint64_t& aPipelineId, TextureFactoryIdentifier*)
{
WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId);
child->AddIPDLReference();

View File

@ -228,7 +228,7 @@ public:
void WillEndTransaction();
PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const uint64_t& aPipelineId) override;
PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const uint64_t& aPipelineId, TextureFactoryIdentifier*) override;
bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor) override;
private:

View File

@ -1556,7 +1556,8 @@ CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
}
PWebRenderBridgeParent*
CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId)
CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId,
TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
#ifndef MOZ_ENABLE_WEBRENDER
// Extra guard since this in the parent process and we don't want a malicious
@ -1575,6 +1576,7 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId)
MonitorAutoLock lock(*sIndirectLayerTreesLock);
MOZ_ASSERT(sIndirectLayerTrees[aPipelineId].mWRBridge == nullptr);
sIndirectLayerTrees[aPipelineId].mWRBridge = mWRBridge;
*aTextureFactoryIdentifier = mCompositor->GetTextureFactoryIdentifier();
return mWRBridge;
}

View File

@ -455,7 +455,8 @@ public:
return !!mApzcTreeManager;
}
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const uint64_t& aPipelineId) override;
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const uint64_t& aPipelineId,
TextureFactoryIdentifier* aTextureFactoryIdentifier) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
private:

View File

@ -192,7 +192,8 @@ CrossProcessCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
}
PWebRenderBridgeParent*
CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId)
CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId,
TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
#ifndef MOZ_ENABLE_WEBRENDER
// Extra guard since this in the parent process and we don't want a malicious
@ -215,7 +216,7 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t&
aPipelineId, nullptr, root->GLContext(), root->WindowState(), root->Compositor());
parent->AddRef(); // IPDL reference
sIndirectLayerTrees[aPipelineId].mWRBridge = parent;
*aTextureFactoryIdentifier = parent->Compositor()->GetTextureFactoryIdentifier();
return parent;
}

View File

@ -154,7 +154,8 @@ public:
virtual void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) override;
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const uint64_t& aPipelineId) override;
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const uint64_t& aPipelineId,
TextureFactoryIdentifier* aTextureFactoryIdentifier) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
protected:

View File

@ -231,7 +231,8 @@ parent:
sync SyncWithCompositor();
// The pipelineId is the same as the layersId
async PWebRenderBridge(uint64_t pipelineId);
sync PWebRenderBridge(uint64_t pipelineId)
returns (TextureFactoryIdentifier textureFactoryIdentifier);
child:
// Send back Compositor Frame Metrics from APZCs so tiled layers can

View File

@ -5,10 +5,12 @@
* 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 LayersSurfaces;
include "mozilla/GfxMessageUtils.h";
include WebRenderMessages;
include protocol PCompositorBridge;
include protocol PTexture;
using WRImageFormat from "mozilla/gfx/webrender.h";
using mozilla::gfx::ByteBuffer from "mozilla/layers/WebRenderTypes.h";
@ -32,8 +34,7 @@ parent:
returns (bool aOutSuccess);
async DPEnd(WebRenderCommand[] commands);
sync DPSyncEnd(WebRenderCommand[] commands);
sync DPGetSnapshot(uint32_t aWidth, uint32_t aHeight)
returns (uint8_t[] aOutImageSnapshot);
sync DPGetSnapshot(PTexture texture, IntRect dirtyRect);
async AddExternalImageId(uint64_t aImageId, uint64_t aAsyncContainerId);
async RemoveExternalImageId(uint64_t aImageId);

View File

@ -6,6 +6,9 @@
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "gfxPlatform.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
namespace mozilla {
@ -101,5 +104,23 @@ WebRenderBridgeChild::DeallocExternalImageId(uint64_t aImageId)
SendRemoveExternalImageId(aImageId);
}
CompositorBridgeChild*
WebRenderBridgeChild::GetCompositorBridgeChild()
{
return static_cast<CompositorBridgeChild*>(Manager());
}
TextureForwarder*
WebRenderBridgeChild::GetTextureForwarder()
{
return static_cast<TextureForwarder*>(GetCompositorBridgeChild());
}
LayersIPCActor*
WebRenderBridgeChild::GetLayersIPCActor()
{
return static_cast<LayersIPCActor*>(GetCompositorBridgeChild());
}
} // namespace layers
} // namespace mozilla

View File

@ -7,6 +7,7 @@
#ifndef mozilla_layers_WebRenderBridgeChild_h
#define mozilla_layers_WebRenderBridgeChild_h
#include "mozilla/layers/KnowsCompositor.h"
#include "mozilla/layers/PWebRenderBridgeChild.h"
namespace mozilla {
@ -17,7 +18,11 @@ class CompositorWidget;
namespace layers {
class CompositorBridgeChild;
class TextureForwarder;
class WebRenderBridgeChild final : public PWebRenderBridgeChild
, public KnowsCompositor
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild)
@ -29,6 +34,11 @@ public:
bool DPBegin(uint32_t aWidth, uint32_t aHeight);
void DPEnd(bool aIsSync = false);
CompositorBridgeChild* GetCompositorBridgeChild();
// KnowsCompositor
TextureForwarder* GetTextureForwarder();
LayersIPCActor* GetLayersIPCActor();
uint64_t AllocExternalImageId(uint64_t aAsyncContainerID);
void DeallocExternalImageId(uint64_t aImageId);

View File

@ -11,12 +11,16 @@
#include "GLContextProvider.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/CompositorVsyncScheduler.h"
#include "mozilla/widget/CompositorWidget.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/WebRenderCompositorOGL.h"
#include "mozilla/widget/CompositorWidget.h"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
WebRenderBridgeParent::WebRenderBridgeParent(const uint64_t& aPipelineId,
widget::CompositorWidget* aWidget,
gl::GLContext* aGlContext,
@ -207,21 +211,64 @@ WebRenderBridgeParent::ProcessWebrenderCommands(InfallibleTArray<WebRenderComman
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDPGetSnapshot(const uint32_t& aWidth,
const uint32_t& aHeight,
InfallibleTArray<uint8_t>* aOutImageSnapshot)
WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture,
const IntRect& aRect)
{
if (mDestroyed) {
return IPC_OK();
}
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
// We kill the content process rather than have it continue with an invalid
// snapshot, that may be too harsh and we could decide to return some sort
// of error to the child process and let it deal with it...
return IPC_FAIL_NO_REASON(this);
}
// XXX Add other TextureHost supports.
// Only BufferTextureHost is supported now.
BufferTextureHost* bufferTexture = texture->AsBufferTextureHost();
if (!bufferTexture) {
// We kill the content process rather than have it continue with an invalid
// snapshot, that may be too harsh and we could decide to return some sort
// of error to the child process and let it deal with it...
return IPC_FAIL_NO_REASON(this);
}
MOZ_ASSERT(bufferTexture->GetBufferDescriptor().type() == BufferDescriptor::TRGBDescriptor);
uint32_t stride = ImageDataSerializer::GetRGBStride(bufferTexture->GetBufferDescriptor().get_RGBDescriptor());
RefPtr<DrawTarget> target =
Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
bufferTexture->GetBuffer(),
bufferTexture->GetSize(),
stride,
bufferTexture->GetFormat());
MOZ_ASSERT(target);
if (!target) {
// We kill the content process rather than have it continue with an invalid
// snapshot, that may be too harsh and we could decide to return some sort
// of error to the child process and let it deal with it...
return IPC_FAIL_NO_REASON(this);
}
MOZ_ASSERT(mWRState);
mGLContext->MakeCurrent();
uint32_t length = 0;
uint32_t capacity = 0;
const uint8_t* webrenderSnapshot = wr_readback_buffer(mWRWindowState, aWidth, aHeight, &length, &capacity);
const uint8_t* webrenderSnapshot = wr_readback_buffer(mWRWindowState, aRect.width, aRect.height, &length, &capacity);
aOutImageSnapshot->ReplaceElementsAt(0, aOutImageSnapshot->Length(), webrenderSnapshot, length);
// TODO: fixup for proper surface format.
RefPtr<DataSourceSurface> snapshot =
Factory::CreateWrappingDataSourceSurface(const_cast<uint8_t*>(webrenderSnapshot),
aRect.width * 4,
IntSize(aRect.width, aRect.height),
SurfaceFormat::B8G8R8A8);
Rect floatRect = Rect(0, 0, aRect.width, aRect.height);
target->DrawSurface(snapshot, floatRect, floatRect, DrawSurfaceOptions(), DrawOptions(1.0f, CompositionOp::OP_SOURCE));
target->Flush();
wr_free_buffer(webrenderSnapshot, length, capacity);

View File

@ -63,9 +63,8 @@ public:
bool* aOutSuccess) override;
mozilla::ipc::IPCResult RecvDPEnd(InfallibleTArray<WebRenderCommand>&& commands) override;
mozilla::ipc::IPCResult RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& commands) override;
mozilla::ipc::IPCResult RecvDPGetSnapshot(const uint32_t& aWidth,
const uint32_t& aHeight,
InfallibleTArray<uint8_t>* aOutImageSnapshot) override;
mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture,
const gfx::IntRect& aRect) override;
mozilla::ipc::IPCResult RecvAddExternalImageId(const uint64_t& aImageId,
const uint64_t& aAsyncContainerId) override;

View File

@ -9,6 +9,7 @@
#include "LayersLogging.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/AsyncCompositionManager.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#include "nsThreadUtils.h"
@ -143,11 +144,14 @@ WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild, uint64_t aLa
{
MOZ_ASSERT(mWRChild == nullptr);
PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId);
TextureFactoryIdentifier textureFactoryIdentifier;
PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId,
&textureFactoryIdentifier);
MOZ_ASSERT(bridge);
mWRChild = static_cast<WebRenderBridgeChild*>(bridge);
LayoutDeviceIntSize size = mWidget->GetClientSize();
WRBridge()->SendCreate(size.width, size.height);
WRBridge()->IdentifyTextureHost(textureFactoryIdentifier);
}
void
@ -174,7 +178,7 @@ WebRenderLayerManager::GetCompositorBridgeChild()
int32_t
WebRenderLayerManager::GetMaxTextureSize() const
{
return 4096;
return WRBridge()->GetMaxTextureSize();
}
bool
@ -228,20 +232,43 @@ WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
void
WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
{
if (!mTarget) {
if (!mTarget || aSize.IsEmpty()) {
return;
}
nsTArray<uint8_t> data;
WRBridge()->SendDPGetSnapshot(aSize.width, aSize.height, &data);
// XXX Add other TextureData supports.
// Only BufferTexture is supported now.
// TODO: fixup for proper surface format.
RefPtr<DataSourceSurface> snapshot =
Factory::CreateWrappingDataSourceSurface(data.Elements(),
aSize.width * 4,
IntSize(aSize.width, aSize.height),
SurfaceFormat::B8G8R8A8);
RefPtr<TextureClient> texture =
TextureClient::CreateForRawBufferAccess(WRBridge(),
SurfaceFormat::B8G8R8A8,
aSize.ToUnknownSize(),
BackendType::CAIRO,
TextureFlags::DEFAULT);
if (!texture) {
return;
}
texture->InitIPDLActor(WRBridge());
if (!texture->GetIPDLActor()) {
return;
}
IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
if (!WRBridge()->SendDPGetSnapshot(texture->GetIPDLActor(), bounds)) {
return;
}
TextureClientAutoLock autoLock(texture, OpenMode::OPEN_READ_ONLY);
if (!autoLock.Succeeded()) {
return;
}
RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
if (!drawTarget || !drawTarget->IsValid()) {
return;
}
RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
/*
static int count = 0;
char filename[100];
@ -250,7 +277,6 @@ WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
gfxUtils::WriteAsPNG(snapshot, filename);
*/
IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
Rect dst(bounds.x, bounds.y, bounds.width, bounds.height);
Rect src(0, 0, bounds.width, bounds.height);

View File

@ -121,7 +121,7 @@ public:
void AddImageKeyForDiscard(WRImageKey);
void DiscardImages();
WebRenderBridgeChild* WRBridge() { return mWRChild; }
WebRenderBridgeChild* WRBridge() const { return mWRChild; }
private:
/**