Bug 867474 - Split BasicShadowableLayerManager into a separate ClientLayerManager. r=nrc

This commit is contained in:
Matt Woodrow
2013-05-01 17:03:25 +12:00
parent 20c051b6be
commit 021593347d
40 changed files with 2097 additions and 1576 deletions

View File

@@ -20,7 +20,6 @@
#define PIXMAN_DONT_DEFINE_STDINT
#include "pixman.h"
#include "BasicTiledThebesLayer.h"
#include "BasicLayersImpl.h"
#include "BasicThebesLayer.h"
#include "BasicContainerLayer.h"
@@ -873,16 +872,6 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT
}
}
static bool
HasOpaqueAncestorLayer(Layer* aLayer)
{
for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
return true;
}
return false;
}
void
BasicLayerManager::PaintLayer(gfxContext* aTarget,
Layer* aLayer,
@@ -917,28 +906,6 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
container->UseIntermediateSurface(),
"ContainerLayer with mask layer should force UseIntermediateSurface");
// If we're a shadowable ContainerLayer, then setup mSupportsComponentAlphaChildren
// in the same way that ContainerLayerComposite will do. Otherwise leave it set to
// true.
ShadowableLayer* shadow = aLayer->AsShadowableLayer();
if (aLayer->GetFirstChild() && shadow && shadow->HasShadow()) {
if (needsGroup) {
if (container->GetEffectiveVisibleRegion().GetNumRects() != 1 ||
!(container->GetContentFlags() & Layer::CONTENT_OPAQUE))
{
const gfx3DMatrix& transform3D = container->GetEffectiveTransform();
gfxMatrix transform;
if (HasOpaqueAncestorLayer(container) &&
transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
container->SetSupportsComponentAlphaChildren(gfxPlatform::GetPlatform()->UsesSubpixelAATextRendering());
}
}
} else {
container->SetSupportsComponentAlphaChildren((container->GetContentFlags() & Layer::CONTENT_OPAQUE) ||
(container->GetParent() && container->GetParent()->SupportsComponentAlphaChildren()));
}
}
gfxContextAutoSaveRestore contextSR;
gfxMatrix transform;
// Will return an identity matrix for 3d transforms, and is handled separately below.
@@ -1066,330 +1033,5 @@ BasicLayerManager::CreateReadbackLayer()
return layer.forget();
}
BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
BasicLayerManager(aWidget), mTargetRotation(ROTATION_0),
mRepeatTransaction(false), mIsRepeatTransaction(false)
{
MOZ_COUNT_CTOR(BasicShadowLayerManager);
}
BasicShadowLayerManager::~BasicShadowLayerManager()
{
MOZ_COUNT_DTOR(BasicShadowLayerManager);
}
int32_t
BasicShadowLayerManager::GetMaxTextureSize() const
{
if (HasShadowManager()) {
return ShadowLayerForwarder::GetMaxTextureSize();
}
return INT32_MAX;
}
void
BasicShadowLayerManager::SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, ScreenRotation aRotation)
{
BasicLayerManager::SetDefaultTargetConfiguration(aDoubleBuffering, aRotation);
mTargetRotation = aRotation;
if (mWidget) {
mTargetBounds = mWidget->GetNaturalBounds();
}
}
void
BasicShadowLayerManager::SetRoot(Layer* aLayer)
{
if (mRoot != aLayer) {
if (HasShadowManager()) {
// Have to hold the old root and its children in order to
// maintain the same view of the layer tree in this process as
// the parent sees. Otherwise layers can be destroyed
// mid-transaction and bad things can happen (v. bug 612573)
if (mRoot) {
Hold(mRoot);
}
ShadowLayerForwarder::SetRoot(Hold(aLayer));
}
BasicLayerManager::SetRoot(aLayer);
}
}
void
BasicShadowLayerManager::Mutated(Layer* aLayer)
{
BasicLayerManager::Mutated(aLayer);
NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
if (HasShadowManager() && ShouldShadow(aLayer)) {
ShadowLayerForwarder::Mutated(Hold(aLayer));
}
}
void
BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
nsRefPtr<gfxContext> targetContext = aTarget;
// If the last transaction was incomplete (a failed DoEmptyTransaction),
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
if (HasShadowManager()) {
ScreenOrientation orientation;
nsIntRect clientBounds;
if (TabChild* window = mWidget->GetOwningTabChild()) {
orientation = window->GetOrientation();
} else {
hal::ScreenConfiguration currentConfig;
hal::GetCurrentScreenConfiguration(&currentConfig);
orientation = currentConfig.orientation();
}
mWidget->GetClientBounds(clientBounds);
ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation, clientBounds, orientation);
// If we're drawing on behalf of a context with async pan/zoom
// enabled, then the entire buffer of thebes layers might be
// composited (including resampling) asynchronously before we get
// a chance to repaint, so we have to ensure that it's all valid
// and not rotated.
if (mWidget) {
if (TabChild* window = mWidget->GetOwningTabChild()) {
mCompositorMightResample = window->IsAsyncPanZoomEnabled();
}
}
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.
if (aTarget && ((aTarget != mDefaultTarget) || Compositor::GetBackend() == LAYERS_BASIC) &&
XRE_GetProcessType() == GeckoProcessType_Default) {
mShadowTarget = aTarget;
gfxASurface::gfxContentType contentType;
if (aTarget->IsCairo()) {
contentType = aTarget->OriginalSurface()->GetContentType();
} else {
contentType = aTarget->GetDrawTarget()->GetFormat() == FORMAT_B8G8R8X8 ?
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
}
// Create a temporary target for ourselves, so that
// mShadowTarget is only drawn to for the window snapshot.
nsRefPtr<gfxASurface> dummy =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(
gfxIntSize(1, 1),
contentType);
mDummyTarget = new gfxContext(dummy);
aTarget = mDummyTarget;
}
}
BasicLayerManager::BeginTransactionWithTarget(aTarget);
}
void
BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
if (mWidget) {
mWidget->PrepareWindowEffects();
}
BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
ForwardTransaction();
if (mRepeatTransaction) {
mRepeatTransaction = false;
mIsRepeatTransaction = true;
BasicLayerManager::BeginTransaction();
BasicShadowLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
mIsRepeatTransaction = false;
} else {
MakeSnapshotIfRequired();
}
}
bool
BasicShadowLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
{
if (!BasicLayerManager::EndEmptyTransaction(aFlags)) {
// Return without calling ForwardTransaction. This leaves the
// ShadowLayerForwarder transaction open; the following
// EndTransaction will complete it.
return false;
}
ForwardTransaction();
MakeSnapshotIfRequired();
return true;
}
void
BasicShadowLayerManager::MakeSnapshotIfRequired()
{
if (!mShadowTarget) {
return;
}
if (mWidget) {
if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
nsIntRect bounds;
mWidget->GetBounds(bounds);
SurfaceDescriptor inSnapshot, snapshot;
if (AllocSurfaceDescriptor(bounds.Size(),
gfxASurface::CONTENT_COLOR_ALPHA,
&inSnapshot) &&
// The compositor will usually reuse |snapshot| and return
// it through |outSnapshot|, but if it doesn't, it's
// responsible for freeing |snapshot|.
remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
AutoOpenSurface opener(OPEN_READ_ONLY, snapshot);
gfxASurface* source = opener.Get();
mShadowTarget->DrawSurface(source, source->GetSize());
}
if (IsSurfaceDescriptorValid(snapshot)) {
ShadowLayerForwarder::DestroySharedSurface(&snapshot);
}
}
}
mShadowTarget = nullptr;
mDummyTarget = nullptr;
}
void
BasicShadowLayerManager::ForwardTransaction()
{
RenderTraceScope rendertrace("Foward Transaction", "000090");
mPhase = PHASE_FORWARD;
// forward this transaction's changeset to our LayerManagerComposite
AutoInfallibleTArray<EditReply, 10> replies;
if (HasShadowManager() && ShadowLayerForwarder::EndTransaction(&replies)) {
for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
const EditReply& reply = replies[i];
switch (reply.type()) {
case EditReply::TOpContentBufferSwap: {
MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap"));
const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap();
CompositableChild* compositableChild =
static_cast<CompositableChild*>(obs.compositableChild());
ContentClientRemote* contentClient =
static_cast<ContentClientRemote*>(compositableChild->GetCompositableClient());
MOZ_ASSERT(contentClient);
contentClient->SwapBuffers(obs.frontUpdatedRegion());
break;
}
case EditReply::TOpTextureSwap: {
MOZ_LAYERS_LOG(("[LayersForwarder] TextureSwap"));
const OpTextureSwap& ots = reply.get_OpTextureSwap();
CompositableChild* compositableChild =
static_cast<CompositableChild*>(ots.compositableChild());
MOZ_ASSERT(compositableChild);
compositableChild->GetCompositableClient()
->SetDescriptorFromReply(ots.textureId(), ots.image());
break;
}
default:
NS_RUNTIMEABORT("not reached");
}
}
} else if (HasShadowManager()) {
NS_WARNING("failed to forward Layers transaction");
}
mPhase = PHASE_NONE;
// this may result in Layers being deleted, which results in
// PLayer::Send__delete__() and DeallocShmem()
mKeepAlive.Clear();
}
ShadowableLayer*
BasicShadowLayerManager::Hold(Layer* aLayer)
{
NS_ABORT_IF_FALSE(HasShadowManager(),
"top-level tree, no shadow tree to remote to");
ShadowableLayer* shadowable = ToShadowable(aLayer);
NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
mKeepAlive.AppendElement(aLayer);
return shadowable;
}
bool
BasicShadowLayerManager::IsCompositingCheap()
{
// Whether compositing is cheap depends on the parent backend.
return mShadowManager &&
LayerManager::IsCompositingCheap(GetCompositorBackendType());
}
void
BasicShadowLayerManager::SetIsFirstPaint()
{
ShadowLayerForwarder::SetIsFirstPaint();
}
void
BasicShadowLayerManager::ClearCachedResources(Layer* aSubtree)
{
MOZ_ASSERT(!HasShadowManager() || !aSubtree);
if (PLayerTransactionChild* manager = GetShadowManager()) {
manager->SendClearCachedResources();
}
BasicLayerManager::ClearCachedResources(aSubtree);
}
bool
BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY,
bool aDrawingCritical)
{
#ifdef MOZ_WIDGET_ANDROID
Layer* primaryScrollable = GetPrimaryScrollableLayer();
if (primaryScrollable) {
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
// This is derived from the code in
// gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
float devPixelRatioX = 1 / rootTransform.GetXScale();
float devPixelRatioY = 1 / rootTransform.GetYScale();
const gfx::Rect& metricsDisplayPort =
(aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
metrics.mCriticalDisplayPort : metrics.mDisplayPort;
gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
(metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
metricsDisplayPort.width * devPixelRatioX,
metricsDisplayPort.height * devPixelRatioY);
return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
aViewport, aScaleX, aScaleY);
}
#endif
return false;
}
BasicShadowableLayer::~BasicShadowableLayer()
{
if (HasShadow()) {
PLayerChild::Send__delete__(GetShadow());
}
MOZ_COUNT_DTOR(BasicShadowableLayer);
}
}
}