author | Chris Jones <jones.chris.g@gmail.com> |
Wed, 21 Jul 2010 16:17:33 -0500 | |
changeset 48143 | 595b4c395ba21affefb53c3db40846241ea92571 |
parent 48142 | 77ceebc9b2f33c8e866da48be5c2f8524dde5acf |
child 48144 | eaa79dbf259c99d28c5ea424ad1f9780d93171c9 |
push id | 14589 |
push user | cjones@mozilla.com |
push date | Fri, 23 Jul 2010 17:12:29 +0000 |
treeherder | mozilla-central@49185ce20807 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 570294 |
milestone | 2.0b3pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
gfx/layers/ThebesLayerBuffer.h | file | annotate | diff | comparison | revisions | |
gfx/layers/basic/BasicLayers.cpp | file | annotate | diff | comparison | revisions |
--- a/gfx/layers/ThebesLayerBuffer.h +++ b/gfx/layers/ThebesLayerBuffer.h @@ -151,16 +151,27 @@ protected: }; nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide); void DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide, float aOpacity); void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity); const nsIntRect& BufferRect() const { return mBufferRect; } const nsIntPoint& BufferRotation() const { return mBufferRotation; } + already_AddRefed<gfxASurface> + SetBuffer(gfxASurface* aBuffer, + const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation) + { + gfxASurface* tmp = mBuffer; + mBuffer = aBuffer; + mBufferRect = aBufferRect; + mBufferRotation = aBufferRotation; + return tmp; + } + private: PRBool BufferSizeOkFor(const nsIntSize& aSize) { return (aSize == mBufferRect.Size() || (SizedToVisibleBounds != mBufferSizePolicy && aSize < mBufferRect.Size())); }
--- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -222,18 +222,51 @@ BasicContainerLayer::RemoveChildInternal aChild->SetNextSibling(nsnull); aChild->SetPrevSibling(nsnull); aChild->SetParent(nsnull); NS_RELEASE(aChild); } +class BasicThebesLayer; +class BasicThebesLayerBuffer : public ThebesLayerBuffer { + typedef ThebesLayerBuffer Base; + +public: + BasicThebesLayerBuffer(BasicThebesLayer* aLayer) + : Base(ContainsVisibleBounds) + , mLayer(aLayer) + {} + + virtual ~BasicThebesLayerBuffer() + {} + + using Base::BufferRect; + using Base::BufferRotation; + + /** + * Complete the drawing operation. The region to draw must have been + * drawn before this is called. The contents of the buffer are drawn + * to aTarget. + */ + void DrawTo(ThebesLayer* aLayer, PRBool aIsOpaqueContent, + gfxContext* aTarget, float aOpacity); + + virtual already_AddRefed<gfxASurface> + CreateBuffer(ContentType aType, const nsIntSize& aSize); + +private: + BasicThebesLayer* mLayer; +}; + class BasicThebesLayer : public ThebesLayer, BasicImplData { public: + typedef BasicThebesLayerBuffer Buffer; + BasicThebesLayer(BasicLayerManager* aLayerManager) : ThebesLayer(aLayerManager, static_cast<BasicImplData*>(this)), mBuffer(this) { MOZ_COUNT_CTOR(BasicThebesLayer); } virtual ~BasicThebesLayer() { @@ -252,46 +285,16 @@ public: "Can only set properties in construction phase"); mValidRegion.Sub(mValidRegion, aRegion); } virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData, float aOpacity); - -protected: - BasicLayerManager* BasicManager() - { - return static_cast<BasicLayerManager*>(mManager); - } - - class Buffer : public ThebesLayerBuffer { - public: - Buffer(BasicThebesLayer* aLayer) - : ThebesLayerBuffer(ContainsVisibleBounds) - , mLayer(aLayer) - {} - - /** - * Complete the drawing operation. The region to draw must have been - * drawn before this is called. The contents of the buffer are drawn - * to aTarget. - */ - void DrawTo(PRBool aIsOpaqueContent, gfxContext* aTarget, float aOpacity); - - virtual already_AddRefed<gfxASurface> - CreateBuffer(ContentType aType, const nsIntSize& aSize) - { - return mLayer->CreateBuffer(aType, aSize); - } - - private: - BasicThebesLayer* mLayer; - }; virtual already_AddRefed<gfxASurface> CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) { nsRefPtr<gfxASurface> referenceSurface = mBuffer.GetBuffer(); if (!referenceSurface) { gfxContext* defaultTarget = BasicManager()->GetDefaultTarget(); if (defaultTarget) { @@ -304,16 +307,34 @@ protected: referenceSurface = BasicManager()->GetTarget()->CurrentSurface(); } } } return referenceSurface->CreateSimilarSurface( aType, gfxIntSize(aSize.width, aSize.height)); } +protected: + BasicLayerManager* BasicManager() + { + return static_cast<BasicLayerManager*>(mManager); + } + + virtual void + PaintBuffer(gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + const nsIntRegion& aRegionToInvalidate, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) + { + aCallback(this, aContext, aRegionToDraw, aRegionToInvalidate, + aCallbackData); + mValidRegion.Or(mValidRegion, aRegionToDraw); + } + Buffer mBuffer; }; static void ClipToContain(gfxContext* aContext, const nsIntRect& aRect) { gfxRect deviceRect = aContext->UserToDevice(gfxRect(aRect.x, aRect.y, aRect.width, aRect.height)); @@ -368,44 +389,52 @@ BasicThebesLayer::Paint(gfxContext* aCon mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); if (state.mContext) { // The area that became invalid and is visible needs to be repainted // (this could be the whole visible area if our buffer switched // from RGB to RGBA, because we might need to repaint with // subpixel AA) state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion); - aCallback(this, state.mContext, state.mRegionToDraw, - state.mRegionToInvalidate, aCallbackData); - mValidRegion.Or(mValidRegion, state.mRegionToDraw); + PaintBuffer(state.mContext, + state.mRegionToDraw, state.mRegionToInvalidate, + aCallback, aCallbackData); } else { // It's possible that state.mRegionToInvalidate is nonempty here, // if we are shrinking the valid region to nothing. NS_ASSERTION(state.mRegionToDraw.IsEmpty(), "If we need to draw, we should have a context"); } } - mBuffer.DrawTo(isOpaqueContent, target, aOpacity); + mBuffer.DrawTo(this, isOpaqueContent, target, aOpacity); } void -BasicThebesLayer::Buffer::DrawTo(PRBool aIsOpaqueContent, - gfxContext* aTarget, - float aOpacity) +BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, + PRBool aIsOpaqueContent, + gfxContext* aTarget, + float aOpacity) { aTarget->Save(); - ClipToRegion(aTarget, mLayer->GetVisibleRegion()); + ClipToRegion(aTarget, aLayer->GetVisibleRegion()); if (aIsOpaqueContent) { aTarget->SetOperator(gfxContext::OPERATOR_SOURCE); } DrawBufferWithRotation(aTarget, aOpacity); aTarget->Restore(); } +already_AddRefed<gfxASurface> +BasicThebesLayerBuffer::CreateBuffer(ContentType aType, + const nsIntSize& aSize) +{ + return mLayer->CreateBuffer(aType, aSize); +} + class BasicImageLayer : public ImageLayer, BasicImplData { public: BasicImageLayer(BasicLayerManager* aLayerManager) : ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)) { MOZ_COUNT_CTOR(BasicImageLayer); } virtual ~BasicImageLayer() @@ -1173,35 +1202,109 @@ BasicShadowableContainerLayer::RemoveChi ShadowManager()->Hold(aChild)); } BasicContainerLayer::RemoveChild(aChild); } class BasicShadowableThebesLayer : public BasicThebesLayer, public BasicShadowableLayer { + typedef BasicThebesLayer Base; + public: BasicShadowableThebesLayer(BasicShadowLayerManager* aManager) : BasicThebesLayer(aManager) { MOZ_COUNT_CTOR(BasicShadowableThebesLayer); } virtual ~BasicShadowableThebesLayer() { + if (mBackBuffer) + BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBuffer); MOZ_COUNT_DTOR(BasicShadowableThebesLayer); } virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { aAttrs = ThebesLayerAttributes(GetValidRegion()); } virtual Layer* AsLayer() { return this; } virtual ShadowableLayer* AsShadowableLayer() { return this; } + + virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer) + { + mBackBuffer = aBuffer; + } + +private: + BasicShadowLayerManager* BasicManager() + { + return static_cast<BasicShadowLayerManager*>(mManager); + } + + NS_OVERRIDE virtual void + PaintBuffer(gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + const nsIntRegion& aRegionToInvalidate, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData); + + NS_OVERRIDE virtual already_AddRefed<gfxASurface> + CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize); + + nsRefPtr<gfxSharedImageSurface> mBackBuffer; + nsIntSize mBufferSize; }; + +void +BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + const nsIntRegion& aRegionToInvalidate, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) +{ + NS_ABORT_IF_FALSE(!!mBackBuffer, "should have a back buffer by now"); + + Base::PaintBuffer(aContext, aRegionToDraw, aRegionToInvalidate, + aCallback, aCallbackData); + + nsRefPtr<gfxContext> tmpCtx = new gfxContext(mBackBuffer); + tmpCtx->DrawSurface(aContext->OriginalSurface(), + gfxIntSize(mBufferSize.width, mBufferSize.height)); + + BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this), + mBuffer.BufferRect(), + mBuffer.BufferRotation(), + mBackBuffer); +} + +already_AddRefed<gfxASurface> +BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType, + const nsIntSize& aSize) +{ + nsRefPtr<gfxSharedImageSurface> tmpFront; + // XXX error handling + if (!BasicManager()->AllocDoubleBuffer(gfxIntSize(aSize.width, aSize.height), + gfxASurface::ImageFormatARGB32, + getter_AddRefs(tmpFront), + getter_AddRefs(mBackBuffer))) + NS_RUNTIMEABORT("creating ThebesLayer 'back buffer' failed!"); + mBufferSize = aSize; + + BasicManager()->CreatedThebesBuffer(BasicManager()->Hold(this), + // only |aSize| really matters + // here, since Painted() soon + // follows + nsIntRect(nsIntPoint(0, 0), aSize), + tmpFront); + + return Base::CreateBuffer(aType, aSize); +} + class BasicShadowableImageLayer : public BasicImageLayer, public BasicShadowableLayer { public: BasicShadowableImageLayer(BasicShadowLayerManager* aManager) : BasicImageLayer(aManager) { @@ -1378,44 +1481,119 @@ BasicShadowableCanvasLayer::Paint(gfxCon // the shmem back buffer nsRefPtr<gfxContext> tmpCtx = new gfxContext(mBackBuffer); tmpCtx->DrawSurface(mSurface, gfxSize(mBounds.width, mBounds.height)); BasicManager()->PaintedCanvas(BasicManager()->Hold(this), mBackBuffer); } +class ShadowThebesLayerBuffer : public BasicThebesLayerBuffer +{ + typedef BasicThebesLayerBuffer Base; + +public: + ShadowThebesLayerBuffer() + : Base(NULL) + { + MOZ_COUNT_CTOR(ShadowThebesLayerBuffer); + } + + ~ShadowThebesLayerBuffer() + { + MOZ_COUNT_DTOR(ShadowThebesLayerBuffer); + } + + already_AddRefed<gfxSharedImageSurface> + Swap(gfxSharedImageSurface* aNewFrontBuffer, + const nsIntRect& aBufferRect, + const nsIntPoint& aRotation=nsIntPoint(0, 0)) + { + nsRefPtr<gfxASurface> newBackBuffer = SetBuffer(aNewFrontBuffer, + aBufferRect, aRotation); + return static_cast<gfxSharedImageSurface*>(newBackBuffer.forget().get()); + } + +protected: + virtual already_AddRefed<gfxASurface> + CreateBuffer(ContentType aType, const nsIntSize& aSize) + { + NS_RUNTIMEABORT("ShadowThebesLayer can't paint content"); + return nsnull; + } +}; class BasicShadowThebesLayer : public ShadowThebesLayer, BasicImplData { public: BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager) : ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this)) { MOZ_COUNT_CTOR(BasicShadowThebesLayer); } - virtual ~BasicShadowThebesLayer() - { - MOZ_COUNT_DTOR(BasicShadowThebesLayer); - } + virtual ~BasicShadowThebesLayer(); virtual already_AddRefed<gfxSharedImageSurface> Swap(gfxSharedImageSurface* aNewFront, const nsIntRect& aBufferRect, const nsIntPoint& aRotation) - { return nsnull; } + { + return mFrontBuffer.Swap(aNewFront, aBufferRect, aRotation); + } virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData, - float aOpacity) - {} + float aOpacity); MOZ_LAYER_DECL_NAME("BasicShadowThebesLayer", TYPE_SHADOW) + +private: + BasicShadowLayerManager* BasicManager() + { + return static_cast<BasicShadowLayerManager*>(mManager); + } + + ShadowThebesLayerBuffer mFrontBuffer; }; +BasicShadowThebesLayer::~BasicShadowThebesLayer() +{ + nsRefPtr<gfxSharedImageSurface> frontBuffer = + mFrontBuffer.Swap(0, nsIntRect()); + if (frontBuffer) { + BasicManager()->ShadowLayerManager::DestroySharedSurface(frontBuffer); + } + + MOZ_COUNT_DTOR(BasicShadowThebesLayer); +} + +void +BasicShadowThebesLayer::Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData, + float aOpacity) +{ + NS_ASSERTION(BasicManager()->InDrawing(), + "Can only draw in drawing phase"); + NS_ASSERTION(BasicManager()->IsRetained(), + "ShadowThebesLayer makes no sense without retained mode"); + + gfxContext* target = BasicManager()->GetTarget(); + NS_ASSERTION(target, "We shouldn't be called if there's no target"); + + nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface(); + PRBool isOpaqueContent = + (targetSurface->AreSimilarSurfacesSensitiveToContentType() && + aOpacity == 1.0 && + CanUseOpaqueSurface()); + + mFrontBuffer.DrawTo(this, isOpaqueContent, target, aOpacity); +} + + class BasicShadowImageLayer : public ShadowImageLayer, BasicImplData { public: BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) : ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this)) { MOZ_COUNT_CTOR(BasicShadowImageLayer); } virtual ~BasicShadowImageLayer()