Bug 745148, part 7: Create a RefLayer type to temporarily contain a foreign layer subtree during composition. r=BenWa sr=roc

This commit is contained in:
Chris Jones 2012-07-17 16:59:45 -07:00
parent 52df2c5fbb
commit ba57040674
13 changed files with 370 additions and 2 deletions

View File

@ -532,7 +532,13 @@ ContainerLayer::DidInsertChild(Layer* aLayer)
mMayHaveReadbackChild = true;
}
}
void
RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = RefLayerAttributes(GetReferentId());
}
void
LayerManager::StartFrameTimeRecording()
{
@ -751,6 +757,16 @@ ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
return aTo;
}
nsACString&
RefLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
{
ContainerLayer::PrintInfo(aTo, aPrefix);
if (-1 != mId) {
AppendToString(aTo, mId, " [id=", "]");
}
return aTo;
}
nsACString&
ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
{
@ -901,6 +917,10 @@ nsACString&
ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
{ return aTo; }
nsACString&
RefLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
{ return aTo; }
nsACString&
ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
{ return aTo; }

View File

@ -54,6 +54,7 @@ class ImageContainer;
class CanvasLayer;
class ReadbackLayer;
class ReadbackProcessor;
class RefLayer;
class ShadowLayer;
class ShadowableLayer;
class ShadowLayerForwarder;
@ -364,6 +365,12 @@ public:
* Create a ReadbackLayer for this manager's layer tree.
*/
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() { return nsnull; }
/**
* CONSTRUCTION PHASE ONLY
* Create a RefLayer for this manager's layer tree.
*/
virtual already_AddRefed<RefLayer> CreateRefLayer() { return nsnull; }
/**
* Can be called anytime, from any thread.
@ -541,6 +548,7 @@ public:
TYPE_CONTAINER,
TYPE_IMAGE,
TYPE_READBACK,
TYPE_REF,
TYPE_SHADOW,
TYPE_THEBES
};
@ -818,6 +826,12 @@ public:
*/
virtual ContainerLayer* AsContainerLayer() { return nsnull; }
/**
* Dynamic cast to a RefLayer. Returns null if this is not a
* RefLayer.
*/
virtual RefLayer* AsRefLayer() { return nsnull; }
/**
* Dynamic cast to a ShadowLayer. Return null if this is not a
* ShadowLayer. Can be used anytime.
@ -1370,6 +1384,96 @@ protected:
bool mDirty;
};
/**
* ContainerLayer that refers to a "foreign" layer tree, through an
* ID. Usage of RefLayer looks like
*
* Construction phase:
* allocate ID for layer subtree
* create RefLayer, SetReferentId(ID)
*
* Composition:
* look up subtree for GetReferentId()
* ConnectReferentLayer(subtree)
* compose
* ClearReferentLayer()
*
* Clients will usually want to Connect/Clear() on each transaction to
* avoid difficulties managing memory across multiple layer subtrees.
*/
class THEBES_API RefLayer : public ContainerLayer {
friend class LayerManager;
private:
virtual void InsertAfter(Layer* aChild, Layer* aAfter)
{ MOZ_NOT_REACHED("no"); }
virtual void RemoveChild(Layer* aChild)
{ MOZ_NOT_REACHED("no"); }
using ContainerLayer::SetFrameMetrics;
public:
/**
* CONSTRUCTION PHASE ONLY
* Set the ID of the layer's referent.
*/
void SetReferentId(uint64_t aId)
{
MOZ_ASSERT(aId != 0);
mId = aId;
}
/**
* CONSTRUCTION PHASE ONLY
* Connect this ref layer to its referent, temporarily.
* ClearReferentLayer() must be called after composition.
*/
void ConnectReferentLayer(Layer* aLayer)
{
MOZ_ASSERT(!mFirstChild && !mLastChild);
MOZ_ASSERT(!aLayer->GetParent());
mFirstChild = mLastChild = aLayer;
aLayer->SetParent(this);
}
/**
* DRAWING PHASE ONLY
* |aLayer| is the same as the argument to ConnectReferentLayer().
*/
void DetachReferentLayer(Layer* aLayer)
{
MOZ_ASSERT(aLayer == mFirstChild && mFirstChild == mLastChild);
MOZ_ASSERT(aLayer->GetParent() == this);
mFirstChild = mLastChild = nsnull;
aLayer->SetParent(nsnull);
}
// These getters can be used anytime.
virtual RefLayer* AsRefLayer() { return this; }
virtual int64_t GetReferentId() { return mId; }
/**
* DRAWING PHASE ONLY
*/
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
MOZ_LAYER_DECL_NAME("RefLayer", TYPE_REF)
protected:
RefLayer(LayerManager* aManager, void* aImplData)
: ContainerLayer(aManager, aImplData) , mId(0)
{}
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
Layer* mTempReferent;
// 0 is a special value that means "no ID".
uint64_t mId;
};
#ifdef MOZ_DUMP_PAINTING
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf);
void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf);

View File

@ -152,6 +152,42 @@ public:
}
};
class BasicShadowableRefLayer : public RefLayer, public BasicImplData,
public BasicShadowableLayer {
template<class Container>
friend void ContainerComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface,
Container* aContainer);
public:
BasicShadowableRefLayer(BasicShadowLayerManager* aManager) :
RefLayer(aManager, static_cast<BasicImplData*>(this))
{
MOZ_COUNT_CTOR(BasicShadowableRefLayer);
}
virtual ~BasicShadowableRefLayer()
{
MOZ_COUNT_DTOR(BasicShadowableRefLayer);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
BasicShadowableLayer::Disconnect();
}
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
ContainerComputeEffectiveTransforms(aTransformToSurface, this);
}
private:
BasicShadowLayerManager* ShadowManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
}
};
already_AddRefed<ContainerLayer>
BasicLayerManager::CreateContainerLayer()
{
@ -170,6 +206,16 @@ BasicShadowLayerManager::CreateContainerLayer()
return layer.forget();
}
already_AddRefed<RefLayer>
BasicShadowLayerManager::CreateRefLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<BasicShadowableRefLayer> layer =
new BasicShadowableRefLayer(this);
MAYBE_CREATE_SHADOW(Ref);
return layer.forget();
}
already_AddRefed<ShadowContainerLayer>
BasicShadowLayerManager::CreateShadowContainerLayer()
{
@ -178,5 +224,13 @@ BasicShadowLayerManager::CreateShadowContainerLayer()
return layer.forget();
}
already_AddRefed<ShadowRefLayer>
BasicShadowLayerManager::CreateShadowRefLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
// FIXME/IMPL
return nsnull;
}
}
}

View File

@ -115,6 +115,8 @@ public:
{ return nsnull; }
virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer()
{ return nsnull; }
virtual already_AddRefed<ShadowRefLayer> CreateShadowRefLayer()
{ return nsnull; }
virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Basic"); }
@ -231,11 +233,13 @@ public:
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<RefLayer> CreateRefLayer();
virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer();
virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
virtual already_AddRefed<ShadowRefLayer> CreateShadowRefLayer();
ShadowableLayer* Hold(Layer* aLayer);

View File

@ -27,6 +27,13 @@ namespace layers {
static Thread* sCompositorThread = nsnull;
/**
* Lookup the indirect shadow tree for |aId| and return it if it
* exists. Otherwise null is returned. This must only be called on
* the compositor thread.
*/
static Layer* GetIndirectShadowTree(uint64_t aId);
void CompositorParent::StartUp()
{
CreateCompositorMap();
@ -292,6 +299,52 @@ CompositorParent::SetTransformation(float aScale, nsIntPoint aScrollOffset)
mScrollOffset = aScrollOffset;
}
/**
* DRAWING PHASE ONLY
*
* For reach RefLayer in |aRoot|, look up its referent and connect it
* to the layer tree, if found. On exiting scope, detaches all
* resolved referents.
*/
class NS_STACK_CLASS AutoResolveRefLayers {
public:
/**
* |aRoot| must remain valid in the scope of this, which should be
* guaranteed by this helper only being used during the drawing
* phase.
*/
AutoResolveRefLayers(Layer* aRoot) : mRoot(aRoot)
{ WalkTheTree<Resolve>(mRoot, nsnull); }
~AutoResolveRefLayers()
{ WalkTheTree<Detach>(mRoot, nsnull); }
private:
enum Op { Resolve, Detach };
template<Op OP>
void WalkTheTree(Layer* aLayer, Layer* aParent)
{
if (RefLayer* ref = aLayer->AsRefLayer()) {
if (Layer* referent = GetIndirectShadowTree(ref->GetReferentId())) {
if (OP == Resolve) {
ref->ConnectReferentLayer(referent);
} else {
ref->DetachReferentLayer(referent);
}
}
}
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
WalkTheTree<OP>(child, aLayer);
}
}
Layer* mRoot;
AutoResolveRefLayers(const AutoResolveRefLayers&) MOZ_DELETE;
AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) MOZ_DELETE;
};
void
CompositorParent::Composite()
{
@ -305,9 +358,11 @@ CompositorParent::Composite()
return;
}
Layer* aLayer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(aLayer);
TransformShadowTree();
Layer* aLayer = mLayerManager->GetRoot();
mozilla::layers::RenderTraceLayers(aLayer, "0000");
mLayerManager->EndEmptyTransaction();
@ -643,6 +698,12 @@ CompositorParent* CompositorParent::RemoveCompositor(PRUint64 id)
return it->second;
}
static Layer*
GetIndirectShadowTree(uint64_t aId)
{
// IMPL in later patch
return nsnull;
}
} // namespace layers
} // namespace mozilla

View File

@ -30,6 +30,7 @@ struct OpCreateContainerLayer { PLayer layer; };
struct OpCreateImageLayer { PLayer layer; };
struct OpCreateColorLayer { PLayer layer; };
struct OpCreateCanvasLayer { PLayer layer; };
struct OpCreateRefLayer { PLayer layer; };
struct ThebesBuffer {
SurfaceDescriptor buffer;
@ -62,6 +63,7 @@ struct ThebesLayerAttributes {
struct ContainerLayerAttributes{ FrameMetrics metrics; };
struct ColorLayerAttributes { gfxRGBA color; };
struct CanvasLayerAttributes { GraphicsFilterType filter; };
struct RefLayerAttributes { int64_t id; };
struct ImageLayerAttributes {
GraphicsFilterType filter;
bool forceSingleTile;
@ -73,6 +75,7 @@ union SpecificLayerAttributes {
ContainerLayerAttributes;
ColorLayerAttributes;
CanvasLayerAttributes;
RefLayerAttributes;
ImageLayerAttributes;
};
@ -127,6 +130,7 @@ union Edit {
OpCreateImageLayer;
OpCreateColorLayer;
OpCreateCanvasLayer;
OpCreateRefLayer;
OpSetLayerAttributes;

View File

@ -167,6 +167,11 @@ ShadowLayerForwarder::CreatedCanvasLayer(ShadowableLayer* aCanvas)
{
CreatedLayer<OpCreateCanvasLayer>(mTxn, aCanvas);
}
void
ShadowLayerForwarder::CreatedRefLayer(ShadowableLayer* aRef)
{
CreatedLayer<OpCreateRefLayer>(mTxn, aRef);
}
void
ShadowLayerForwarder::DestroyedThebesBuffer(ShadowableLayer* aThebes,

View File

@ -31,6 +31,7 @@ class ShadowContainerLayer;
class ShadowImageLayer;
class ShadowColorLayer;
class ShadowCanvasLayer;
class ShadowRefLayer;
class SurfaceDescriptor;
class ThebesBuffer;
class TiledLayerComposer;
@ -126,6 +127,7 @@ public:
void CreatedImageLayer(ShadowableLayer* aImage);
void CreatedColorLayer(ShadowableLayer* aColor);
void CreatedCanvasLayer(ShadowableLayer* aCanvas);
void CreatedRefLayer(ShadowableLayer* aRef);
/**
* The specified layer is destroying its buffers.
@ -398,6 +400,8 @@ public:
virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer() = 0;
/** CONSTRUCTION PHASE ONLY */
virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer() = 0;
/** CONSTRUCTION PHASE ONLY */
virtual already_AddRefed<ShadowRefLayer> CreateShadowRefLayer() { return nsnull; }
static void PlatformSyncBeforeReplyUpdate();
@ -665,6 +669,20 @@ protected:
{}
};
class ShadowRefLayer : public ShadowLayer,
public RefLayer
{
public:
virtual ShadowLayer* AsShadowLayer() { return this; }
MOZ_LAYER_DECL_NAME("ShadowRefLayer", TYPE_SHADOW)
protected:
ShadowRefLayer(LayerManager* aManager, void* aImplData)
: RefLayer(aManager, aImplData)
{}
};
bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface);
ipc::SharedMemory::SharedMemoryType OptimalShmemType();

View File

@ -191,6 +191,15 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
AsShadowLayer(edit.get_OpCreateCanvasLayer())->Bind(layer);
break;
}
case Edit::TOpCreateRefLayer: {
MOZ_LAYERS_LOG(("[ParentSide] CreateRefLayer"));
nsRefPtr<ShadowRefLayer> layer =
layer_manager()->CreateShadowRefLayer();
layer->SetAllocator(this);
AsShadowLayer(edit.get_OpCreateRefLayer())->Bind(layer);
break;
}
// Attributes
case Edit::TOpSetLayerAttributes: {
@ -256,6 +265,13 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
specific.get_CanvasLayerAttributes().filter());
break;
case Specific::TRefLayerAttributes:
MOZ_LAYERS_LOG(("[ParentSide] ref layer"));
static_cast<RefLayer*>(layer)->SetReferentId(
specific.get_RefLayerAttributes().id());
break;
case Specific::TImageLayerAttributes: {
MOZ_LAYERS_LOG(("[ParentSide] image layer"));

View File

@ -387,5 +387,45 @@ ShadowContainerLayerOGL::CleanupResources()
ContainerCleanupResources(this);
}
ShadowRefLayerOGL::ShadowRefLayerOGL(LayerManagerOGL* aManager)
: ShadowRefLayer(aManager, NULL)
, LayerOGL(aManager)
{
mImplData = static_cast<LayerOGL*>(this);
}
ShadowRefLayerOGL::~ShadowRefLayerOGL()
{
Destroy();
}
void
ShadowRefLayerOGL::Destroy()
{
MOZ_ASSERT(!mFirstChild);
mDestroyed = true;
}
LayerOGL*
ShadowRefLayerOGL::GetFirstChildOGL()
{
if (!mFirstChild) {
return nsnull;
}
return static_cast<LayerOGL*>(mFirstChild->ImplData());
}
void
ShadowRefLayerOGL::RenderLayer(int aPreviousFrameBuffer,
const nsIntPoint& aOffset)
{
ContainerRender(this, aPreviousFrameBuffer, aOffset, mOGLManager);
}
void
ShadowRefLayerOGL::CleanupResources()
{
}
} /* layers */
} /* mozilla */

View File

@ -109,6 +109,37 @@ public:
virtual void CleanupResources();
};
class ShadowRefLayerOGL : public ShadowRefLayer,
public LayerOGL
{
template<class Container>
friend void ContainerRender(Container* aContainer,
int aPreviousFrameBuffer,
const nsIntPoint& aOffset,
LayerManagerOGL* aManager);
public:
ShadowRefLayerOGL(LayerManagerOGL *aManager);
~ShadowRefLayerOGL();
/** LayerOGL implementation */
Layer* GetLayer() { return this; }
void Destroy();
LayerOGL* GetFirstChildOGL();
virtual void RenderLayer(int aPreviousFrameBuffer,
const nsIntPoint& aOffset);
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
virtual void CleanupResources();
};
} /* layers */
} /* mozilla */

View File

@ -1246,5 +1246,15 @@ LayerManagerOGL::CreateShadowCanvasLayer()
return nsRefPtr<ShadowCanvasLayerOGL>(new ShadowCanvasLayerOGL(this)).forget();
}
already_AddRefed<ShadowRefLayer>
LayerManagerOGL::CreateShadowRefLayer()
{
if (LayerManagerOGL::mDestroyed) {
NS_WARNING("Call on destroyed layer manager");
return nsnull;
}
return nsRefPtr<ShadowRefLayerOGL>(new ShadowRefLayerOGL(this)).forget();
}
} /* layers */
} /* mozilla */

View File

@ -138,6 +138,7 @@ public:
virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer();
virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
virtual already_AddRefed<ShadowRefLayer> CreateShadowRefLayer();
virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; }
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("OpenGL"); }