Bug 626602. Part 2: BasicLayers implementation of ReadbackLayer. r=cjones

This commit is contained in:
Robert O'Callahan 2011-02-16 16:43:30 -06:00
parent 1a14aa0939
commit 1619ca83d2
2 changed files with 141 additions and 71 deletions

View File

@ -58,6 +58,7 @@
#include "gfxUtils.h" #include "gfxUtils.h"
#include "ThebesLayerBuffer.h" #include "ThebesLayerBuffer.h"
#include "nsIWidget.h" #include "nsIWidget.h"
#include "ReadbackProcessor.h"
#include "GLContext.h" #include "GLContext.h"
@ -106,9 +107,16 @@ public:
* set up to account for all the properties of the layer (transform, * set up to account for all the properties of the layer (transform,
* opacity, etc). * opacity, etc).
*/ */
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext) {}
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) {} /**
* Like Paint() but called for ThebesLayers with the additional parameters
* they need.
*/
virtual void PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback) {}
virtual ShadowableLayer* AsShadowableLayer() { return nsnull; } virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
@ -380,9 +388,10 @@ public:
mValidRegion.Sub(mValidRegion, aRegion); mValidRegion.Sub(mValidRegion, aRegion);
} }
virtual void Paint(gfxContext* aContext, virtual void PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData); void* aCallbackData,
ReadbackProcessor* aReadback);
virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); } virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); }
@ -507,14 +516,20 @@ PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegio
} }
void void
BasicThebesLayer::Paint(gfxContext* aContext, BasicThebesLayer::PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) void* aCallbackData,
ReadbackProcessor* aReadback)
{ {
NS_ASSERTION(BasicManager()->InDrawing(), NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase"); "Can only draw in drawing phase");
nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface(); nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
nsTArray<ReadbackProcessor::Update> readbackUpdates;
if (aReadback && UsedForReadback()) {
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
}
PRBool canUseOpaqueSurface = CanUseOpaqueSurface(); PRBool canUseOpaqueSurface = CanUseOpaqueSurface();
Buffer::ContentType contentType = Buffer::ContentType contentType =
canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR : canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
@ -525,6 +540,8 @@ BasicThebesLayer::Paint(gfxContext* aContext,
(!canUseOpaqueSurface && (!canUseOpaqueSurface &&
(mContentFlags & CONTENT_COMPONENT_ALPHA) && (mContentFlags & CONTENT_COMPONENT_ALPHA) &&
!MustRetainContent())) { !MustRetainContent())) {
NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
mValidRegion.SetEmpty(); mValidRegion.SetEmpty();
mBuffer.Clear(); mBuffer.Clear();
@ -587,6 +604,20 @@ BasicThebesLayer::Paint(gfxContext* aContext,
} }
mBuffer.DrawTo(this, aContext, opacity); mBuffer.DrawTo(this, aContext, opacity);
for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
ReadbackProcessor::Update& update = readbackUpdates[i];
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
nsRefPtr<gfxContext> ctx =
update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
update.mSequenceCounter);
if (ctx) {
NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
ctx->Translate(gfxPoint(offset.x, offset.y));
mBuffer.DrawTo(this, ctx, 1.0);
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
}
}
} }
static PRBool static PRBool
@ -667,9 +698,7 @@ public:
ImageLayer::SetVisibleRegion(aRegion); ImageLayer::SetVisibleRegion(aRegion);
} }
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext);
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
static void PaintContext(gfxPattern* aPattern, static void PaintContext(gfxPattern* aPattern,
const nsIntRegion& aVisible, const nsIntRegion& aVisible,
@ -691,9 +720,7 @@ protected:
}; };
void void
BasicImageLayer::Paint(gfxContext* aContext, BasicImageLayer::Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
nsRefPtr<gfxPattern> dontcare = nsRefPtr<gfxPattern> dontcare =
GetAndPaintCurrentImage(aContext, GetEffectiveOpacity()); GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
@ -799,9 +826,7 @@ public:
ColorLayer::SetVisibleRegion(aRegion); ColorLayer::SetVisibleRegion(aRegion);
} }
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
PaintColorTo(mColor, GetEffectiveOpacity(), aContext); PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
} }
@ -847,9 +872,7 @@ public:
virtual void Initialize(const Data& aData); virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect); virtual void Updated(const nsIntRect& aRect);
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext);
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
virtual void PaintWithOpacity(gfxContext* aContext, virtual void PaintWithOpacity(gfxContext* aContext,
float aOpacity); float aOpacity);
@ -959,9 +982,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
} }
void void
BasicCanvasLayer::Paint(gfxContext* aContext, BasicCanvasLayer::Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
PaintWithOpacity(aContext, GetEffectiveOpacity()); PaintWithOpacity(aContext, GetEffectiveOpacity());
} }
@ -998,6 +1019,34 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
mUpdatedRect.Empty(); mUpdatedRect.Empty();
} }
class BasicReadbackLayer : public ReadbackLayer,
BasicImplData
{
public:
BasicReadbackLayer(BasicLayerManager* aLayerManager) :
ReadbackLayer(aLayerManager, static_cast<BasicImplData*>(this))
{
MOZ_COUNT_CTOR(BasicReadbackLayer);
}
virtual ~BasicReadbackLayer()
{
MOZ_COUNT_DTOR(BasicReadbackLayer);
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(BasicManager()->InConstruction(),
"Can only set properties in construction phase");
ReadbackLayer::SetVisibleRegion(aRegion);
}
protected:
BasicLayerManager* BasicManager()
{
return static_cast<BasicLayerManager*>(mManager);
}
};
static nsIntRect static nsIntRect
ToOutsideIntRect(const gfxRect &aRect) ToOutsideIntRect(const gfxRect &aRect)
{ {
@ -1298,7 +1347,7 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
MarkLeafLayersCoveredByOpaque(mRoot, MarkLeafLayersCoveredByOpaque(mRoot,
mRoot->GetEffectiveVisibleRegion().GetBounds(), mRoot->GetEffectiveVisibleRegion().GetBounds(),
region); region);
PaintLayer(mRoot, aCallback, aCallbackData); PaintLayer(mRoot, aCallback, aCallbackData, nsnull);
// If we're doing manual double-buffering, we need to avoid drawing // If we're doing manual double-buffering, we need to avoid drawing
// the results of an incomplete transaction to the destination surface. // the results of an incomplete transaction to the destination surface.
@ -1369,7 +1418,8 @@ BasicLayerManager::SetRoot(Layer* aLayer)
void void
BasicLayerManager::PaintLayer(Layer* aLayer, BasicLayerManager::PaintLayer(Layer* aLayer,
DrawThebesLayerCallback aCallback, DrawThebesLayerCallback aCallback,
void* aCallbackData) void* aCallbackData,
ReadbackProcessor* aReadback)
{ {
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect(); const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform(); const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
@ -1431,11 +1481,21 @@ BasicLayerManager::PaintLayer(Layer* aLayer,
(void*)aLayer, data->IsCoveredByOpaque())); (void*)aLayer, data->IsCoveredByOpaque()));
#endif #endif
if (!data->IsCoveredByOpaque()) { if (!data->IsCoveredByOpaque()) {
data->Paint(mTarget, aCallback, aCallbackData); if (aLayer->AsThebesLayer()) {
data->PaintThebes(mTarget, aCallback, aCallbackData, aReadback);
} else {
data->Paint(mTarget);
}
} }
} else { } else {
ReadbackProcessor readback;
if (IsRetained()) {
ContainerLayer* container = static_cast<ContainerLayer*>(aLayer);
readback.BuildUpdates(container);
}
for (; child; child = child->GetNextSibling()) { for (; child; child = child->GetNextSibling()) {
PaintLayer(child, aCallback, aCallbackData); PaintLayer(child, aCallback, aCallbackData, &readback);
if (mTransactionIncomplete) if (mTransactionIncomplete)
break; break;
} }
@ -1519,6 +1579,13 @@ BasicLayerManager::CreateCanvasLayer()
return layer.forget(); return layer.forget();
} }
already_AddRefed<ReadbackLayer>
BasicLayerManager::CreateReadbackLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
return layer.forget();
}
#ifdef MOZ_IPC #ifdef MOZ_IPC
@ -1575,6 +1642,19 @@ ToShadowable(Layer* aLayer)
return ToData(aLayer)->AsShadowableLayer(); return ToData(aLayer)->AsShadowableLayer();
} }
// Some layers, like ReadbackLayers, can't be shadowed and shadowing
// them doesn't make sense anyway
static bool
ShouldShadow(Layer* aLayer)
{
if (!ToShadowable(aLayer)) {
NS_ABORT_IF_FALSE(aLayer->GetType() == Layer::TYPE_READBACK,
"Only expect not to shadow ReadbackLayers");
return false;
}
return true;
}
template<class OpT> template<class OpT>
static BasicShadowableLayer* static BasicShadowableLayer*
GetBasicShadowable(const OpT& op) GetBasicShadowable(const OpT& op)
@ -1622,7 +1702,10 @@ private:
void void
BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter) BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
{ {
if (HasShadow()) { if (HasShadow() && ShouldShadow(aChild)) {
while (aAfter && !ShouldShadow(aAfter)) {
aAfter = aAfter->GetPrevSibling();
}
ShadowManager()->InsertAfter(ShadowManager()->Hold(this), ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
ShadowManager()->Hold(aChild), ShadowManager()->Hold(aChild),
aAfter ? ShadowManager()->Hold(aAfter) : nsnull); aAfter ? ShadowManager()->Hold(aAfter) : nsnull);
@ -1633,7 +1716,7 @@ BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
void void
BasicShadowableContainerLayer::RemoveChild(Layer* aChild) BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
{ {
if (HasShadow()) { if (HasShadow() && ShouldShadow(aChild)) {
ShadowManager()->RemoveChild(ShadowManager()->Hold(this), ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
ShadowManager()->Hold(aChild)); ShadowManager()->Hold(aChild));
} }
@ -1857,9 +1940,7 @@ public:
MOZ_COUNT_DTOR(BasicShadowableImageLayer); MOZ_COUNT_DTOR(BasicShadowableImageLayer);
} }
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext);
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{ {
@ -1890,9 +1971,7 @@ private:
}; };
void void
BasicShadowableImageLayer::Paint(gfxContext* aContext, BasicShadowableImageLayer::Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
gfxIntSize oldSize = mSize; gfxIntSize oldSize = mSize;
nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity()); nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
@ -1977,9 +2056,7 @@ public:
} }
virtual void Initialize(const Data& aData); virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext);
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{ {
@ -2040,11 +2117,9 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
} }
void void
BasicShadowableCanvasLayer::Paint(gfxContext* aContext, BasicShadowableCanvasLayer::Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
BasicCanvasLayer::Paint(aContext, aCallback, aCallbackData); BasicCanvasLayer::Paint(aContext);
if (!HasShadow()) if (!HasShadow())
return; return;
@ -2167,9 +2242,10 @@ public:
} }
} }
virtual void Paint(gfxContext* aContext, virtual void PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData); void* aCallbackData,
ReadbackProcessor* aReadback);
private: private:
BasicShadowLayerManager* BasicManager() BasicShadowLayerManager* BasicManager()
@ -2261,9 +2337,10 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
} }
void void
BasicShadowThebesLayer::Paint(gfxContext* aContext, BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) void* aCallbackData,
ReadbackProcessor* aReadback)
{ {
NS_ASSERTION(BasicManager()->InDrawing(), NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase"); "Can only draw in drawing phase");
@ -2357,9 +2434,7 @@ public:
mFrontSurface = nsnull; mFrontSurface = nsnull;
} }
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext);
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
protected: protected:
BasicShadowLayerManager* BasicManager() BasicShadowLayerManager* BasicManager()
@ -2390,9 +2465,7 @@ BasicShadowImageLayer::Swap(gfxSharedImageSurface* newFront)
} }
void void
BasicShadowImageLayer::Paint(gfxContext* aContext, BasicShadowImageLayer::Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
if (!mFrontSurface) { if (!mFrontSurface) {
return; return;
@ -2425,9 +2498,7 @@ public:
MOZ_COUNT_DTOR(BasicShadowColorLayer); MOZ_COUNT_DTOR(BasicShadowColorLayer);
} }
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext); BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
} }
@ -2469,9 +2540,7 @@ public:
mFrontSurface = nsnull; mFrontSurface = nsnull;
} }
virtual void Paint(gfxContext* aContext, virtual void Paint(gfxContext* aContext);
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData);
private: private:
BasicShadowLayerManager* BasicManager() BasicShadowLayerManager* BasicManager()
@ -2503,9 +2572,7 @@ BasicShadowCanvasLayer::Swap(gfxSharedImageSurface* newFront)
} }
void void
BasicShadowCanvasLayer::Paint(gfxContext* aContext, BasicShadowCanvasLayer::Paint(gfxContext* aContext)
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ {
NS_ASSERTION(BasicManager()->InDrawing(), NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase"); "Can only draw in drawing phase");
@ -2676,7 +2743,7 @@ BasicShadowLayerManager::Mutated(Layer* aLayer)
BasicLayerManager::Mutated(aLayer); BasicLayerManager::Mutated(aLayer);
NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase"); NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
if (HasShadowManager()) { if (HasShadowManager() && ShouldShadow(aLayer)) {
ShadowLayerForwarder::Mutated(Hold(aLayer)); ShadowLayerForwarder::Mutated(Hold(aLayer));
} }
} }

View File

@ -60,6 +60,7 @@ class ShadowContainerLayer;
class ShadowImageLayer; class ShadowImageLayer;
class ShadowCanvasLayer; class ShadowCanvasLayer;
class ShadowColorLayer; class ShadowColorLayer;
class ReadbackProcessor;
/** /**
* This is a cairo/Thebes-only, main-thread-only implementation of layers. * This is a cairo/Thebes-only, main-thread-only implementation of layers.
@ -152,16 +153,17 @@ public:
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer(); virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer(); virtual already_AddRefed<ImageContainer> CreateImageContainer();
virtual already_AddRefed<ColorLayer> CreateColorLayer(); virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer() virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer()
{ return NULL; } { return nsnull; }
virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer() virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer()
{ return NULL; } { return nsnull; }
virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer() virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer()
{ return NULL; } { return nsnull; }
virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer() virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer()
{ return NULL; } { return nsnull; }
virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer() virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer()
{ return NULL; } { return nsnull; }
virtual LayersBackend GetBackendType() { return LAYERS_BASIC; } virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Basic"); } virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Basic"); }
@ -197,7 +199,8 @@ protected:
// Paints aLayer to mTarget. // Paints aLayer to mTarget.
void PaintLayer(Layer* aLayer, void PaintLayer(Layer* aLayer,
DrawThebesLayerCallback aCallback, DrawThebesLayerCallback aCallback,
void* aCallbackData); void* aCallbackData,
ReadbackProcessor* aReadback);
// Clear the contents of a layer // Clear the contents of a layer
void ClearLayer(Layer* aLayer); void ClearLayer(Layer* aLayer);