Bug 947781 - Part 4: Add ReadbackLayer functionality to ClientLayerManager. r=mattwoodrow

This commit is contained in:
Bas Schouten 2014-07-30 15:38:47 +02:00
parent 337d782d7e
commit e9f3470cf0
8 changed files with 144 additions and 11 deletions

View File

@ -15,6 +15,8 @@
#include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE
#include "nsRegion.h" // for nsIntRegion
#include "nsTArray.h" // for nsAutoTArray
#include "ReadbackProcessor.h"
#include "ClientThebesLayer.h"
namespace mozilla {
namespace layers {
@ -55,13 +57,20 @@ public:
nsAutoTArray<Layer*, 12> children;
SortChildrenBy3DZOrder(children);
ReadbackProcessor readback;
readback.BuildUpdates(this);
for (uint32_t i = 0; i < children.Length(); i++) {
Layer* child = children.ElementAt(i);
if (child->GetEffectiveVisibleRegion().IsEmpty()) {
continue;
}
ToClientLayer(child)->RenderLayer();
if (child->GetType() != TYPE_THEBES) {
ToClientLayer(child)->RenderLayer();
} else {
static_cast<ClientThebesLayer*>(child)->RenderLayer(&readback);
}
if (!ClientManager()->GetRepeatTransaction() &&
!child->GetInvalidRegion().IsEmpty()) {

View File

@ -21,6 +21,7 @@
#include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/TextureClientPool.h" // for TextureClientPool
#include "mozilla/layers/SimpleTextureClientPool.h" // for SimpleTextureClientPool
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
#include "nsAString.h"
#include "nsIWidget.h" // for nsIWidget
#include "nsIWidgetListener.h"
@ -116,6 +117,13 @@ ClientLayerManager::Mutated(Layer* aLayer)
mForwarder->Mutated(Hold(aLayer));
}
already_AddRefed<ReadbackLayer>
ClientLayerManager::CreateReadbackLayer()
{
nsRefPtr<ReadbackLayer> layer = new ClientReadbackLayer(this);
return layer.forget();
}
void
ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{

View File

@ -88,6 +88,7 @@ public:
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<RefLayer> CreateRefLayer();

View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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/. */
#ifndef GFX_CLIENTREADBACKLAYER_H
#define GFX_CLIENTREADBACKLAYER_H
#include "ClientLayerManager.h"
#include "ReadbackLayer.h"
namespace mozilla {
namespace layers {
class ClientReadbackLayer :
public ReadbackLayer,
public ClientLayer
{
public:
ClientReadbackLayer(ClientLayerManager *aManager)
: ReadbackLayer(aManager, nullptr)
{
mImplData = static_cast<ClientLayer*>(this);
}
virtual Layer* AsLayer() { return this; }
virtual void RenderLayer() {}
};
} /* layers */
} /* mozilla */
#endif /* GFX_CLIENTREADBACKLAYER_H */

View File

@ -24,6 +24,7 @@
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "nsRect.h" // for nsIntRect
#include "gfx2DGlue.h"
#include "ReadbackProcessor.h"
namespace mozilla {
namespace layers {
@ -104,7 +105,7 @@ ClientThebesLayer::PaintThebes()
}
void
ClientThebesLayer::RenderLayer()
ClientThebesLayer::RenderLayer(ReadbackProcessor *aReadback)
{
if (GetMaskLayer()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
@ -120,9 +121,16 @@ ClientThebesLayer::RenderLayer()
MOZ_ASSERT(mContentClient->GetForwarder());
}
nsTArray<ReadbackProcessor::Update> readbackUpdates;
nsIntRegion readbackRegion;
if (aReadback && UsedForReadback()) {
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
}
IntPoint origin(mVisibleRegion.GetBounds().x, mVisibleRegion.GetBounds().y);
mContentClient->BeginPaint();
PaintThebes();
mContentClient->EndPaint();
mContentClient->EndPaint(&readbackUpdates);
}
bool

View File

@ -69,7 +69,9 @@ public:
mValidRegion.Sub(mValidRegion, mInvalidRegion);
}
virtual void RenderLayer();
virtual void RenderLayer() { RenderLayer(nullptr); }
virtual void RenderLayer(ReadbackProcessor *aReadback);
virtual void ClearCachedResources()
{

View File

@ -36,6 +36,11 @@
#include "gfxPlatformGtk.h"
#endif
#include "gfx2DGlue.h"
#include "ReadbackLayer.h"
#include <vector>
using namespace std;
namespace mozilla {
@ -101,7 +106,7 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
}
void
ContentClient::EndPaint()
ContentClient::EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
{
// It is very important that this is called after any overridden EndPaint behaviour,
// because destroying textures is a three stage process:
@ -157,6 +162,64 @@ ContentClientRemoteBuffer::DestroyBuffers()
DestroyFrontBuffer();
}
class RemoteBufferReadbackProcessor : public TextureReadbackSink
{
public:
RemoteBufferReadbackProcessor(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates,
const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation)
: mReadbackUpdates(*aReadbackUpdates)
, mBufferRect(aBufferRect)
, mBufferRotation(aBufferRotation)
{
for (uint32_t i = 0; i < mReadbackUpdates.Length(); ++i) {
mLayerRefs.push_back(mReadbackUpdates[i].mLayer);
}
}
virtual void ProcessReadback(gfx::DataSourceSurface *aSourceSurface)
{
SourceRotatedBuffer rotBuffer(aSourceSurface, nullptr, mBufferRect, mBufferRotation);
for (uint32_t i = 0; i < mReadbackUpdates.Length(); ++i) {
ReadbackProcessor::Update& update = mReadbackUpdates[i];
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
ReadbackSink* sink = update.mLayer->GetSink();
if (!sink) {
continue;
}
if (!aSourceSurface) {
sink->SetUnknown(update.mSequenceCounter);
continue;
}
nsRefPtr<gfxContext> ctx =
sink->BeginUpdate(update.mUpdateRect + offset, update.mSequenceCounter);
if (!ctx) {
continue;
}
DrawTarget* dt = ctx->GetDrawTarget();
dt->SetTransform(Matrix::Translation(offset.x, offset.y));
rotBuffer.DrawBufferWithRotation(dt, RotatedBuffer::BUFFER_BLACK);
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
}
}
private:
nsTArray<ReadbackProcessor::Update> mReadbackUpdates;
// This array is used to keep the layers alive until the callback.
vector<RefPtr<Layer>> mLayerRefs;
nsIntRect mBufferRect;
nsIntPoint mBufferRotation;
};
void
ContentClientRemoteBuffer::BeginPaint()
{
@ -173,8 +236,10 @@ ContentClientRemoteBuffer::BeginPaint()
}
void
ContentClientRemoteBuffer::EndPaint()
ContentClientRemoteBuffer::EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
{
MOZ_ASSERT(!mTextureClientOnWhite || !aReadbackUpdates || aReadbackUpdates->Length() == 0);
// XXX: We might still not have a texture client if PaintThebes
// decided we didn't need one yet because the region to draw was empty.
SetBufferProvider(nullptr);
@ -187,12 +252,18 @@ ContentClientRemoteBuffer::EndPaint()
mOldTextures.Clear();
if (mTextureClient && mTextureClient->IsLocked()) {
if (aReadbackUpdates->Length() > 0) {
RefPtr<TextureReadbackSink> readbackSink = new RemoteBufferReadbackProcessor(aReadbackUpdates, mBufferRect, mBufferRotation);
mTextureClient->SetReadbackSink(readbackSink);
}
mTextureClient->Unlock();
}
if (mTextureClientOnWhite && mTextureClientOnWhite->IsLocked()) {
mTextureClientOnWhite->Unlock();
}
ContentClientRemote::EndPaint();
ContentClientRemote::EndPaint(aReadbackUpdates);
}
void

View File

@ -21,6 +21,7 @@
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/TextureClient.h" // for TextureClient
#include "mozilla/mozalloc.h" // for operator delete
#include "ReadbackProcessor.h" // For ReadbackProcessor::Update
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsPoint.h" // for nsIntPoint
#include "nsRect.h" // for nsIntRect
@ -103,7 +104,7 @@ public:
// call before and after painting into this content client
virtual void BeginPaint() {}
virtual void EndPaint();
virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr);
};
/**
@ -231,7 +232,7 @@ public:
* are affected by mapping/unmapping.
*/
virtual void BeginPaint() MOZ_OVERRIDE;
virtual void EndPaint() MOZ_OVERRIDE;
virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr) MOZ_OVERRIDE;
virtual void Updated(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,
@ -430,7 +431,7 @@ public:
const nsIntRegion& aVisibleRegion,
bool aDidSelfCopy);
virtual void EndPaint()
virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr)
{
if (IsSurfaceDescriptorValid(mUpdateDescriptor)) {
mForwarder->DestroySharedSurface(&mUpdateDescriptor);
@ -438,7 +439,7 @@ public:
if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) {
mForwarder->DestroySharedSurface(&mUpdateDescriptorOnWhite);
}
ContentClientRemote::EndPaint();
ContentClientRemote::EndPaint(aReadbackUpdates);
}
private: