diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 1d619180efd6..a1ffd9eb9366 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -200,6 +200,17 @@ LayerManager::CreateOptimalSurface(const gfxIntSize &aSize, CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFormat)); } +#ifdef DEBUG +void +LayerManager::Mutated(Layer* aLayer) +{ + NS_ABORT_IF_FALSE(!aLayer->GetTileSourceRect() || + (LAYERS_BASIC == GetBackendType() && + Layer::TYPE_IMAGE == aLayer->GetType()), + "Tiling not supported for this manager/layer type"); +} +#endif // DEBUG + //-------------------------------------------------- // Layer diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 927c0c1bc75c..a31428b5779a 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -359,8 +359,15 @@ public: /** * CONSTRUCTION PHASE ONLY * Called when a managee has mutated. + * Subclasses overriding this method must first call their + * superclass's impl */ +#ifdef DEBUG + // In debug builds, we check some properties of |aLayer|. + virtual void Mutated(Layer* aLayer); +#else virtual void Mutated(Layer* aLayer) { } +#endif /** * CONSTRUCTION PHASE ONLY @@ -641,6 +648,10 @@ public: * ColorLayers, a source rect for tiling doesn't make sense at all. * * If aRect is null no tiling will be performed. + * + * NB: this interface is only implemented for BasicImageLayers, and + * then only for source rects the same size as the layers' + * underlying images. */ void SetTileSourceRect(const nsIntRect* aRect) { diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 57dba5534f62..2ca6bc62e992 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -667,7 +667,8 @@ public: void* aCallbackData); static void PaintContext(gfxPattern* aPattern, - const gfxIntSize& aSize, + const nsIntRegion& aVisible, + const nsIntRect* aTileSourceRect, float aOpacity, gfxContext* aContext); @@ -712,13 +713,16 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext, pat->SetFilter(mFilter); - PaintContext(pat, mSize, aOpacity, aContext); + PaintContext(pat, + nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)), + GetTileSourceRect(), aOpacity, aContext); return pat.forget(); } /*static*/ void BasicImageLayer::PaintContext(gfxPattern* aPattern, - const gfxIntSize& aSize, + const nsIntRegion& aVisible, + const nsIntRect* aTileSourceRect, float aOpacity, gfxContext* aContext) { @@ -736,14 +740,34 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern, extend = gfxPattern::EXTEND_NONE; } - aPattern->SetExtend(extend); + if (!aTileSourceRect) { + aContext->NewPath(); + // No need to snap here; our transform has already taken care of it. + // XXX true for arbitrary regions? Don't care yet though + gfxUtils::PathFromRegion(aContext, aVisible); + aPattern->SetExtend(extend); + aContext->SetPattern(aPattern); + aContext->FillWithOpacity(aOpacity); + } else { + nsRefPtr source = aPattern->GetSurface(); + NS_ABORT_IF_FALSE(source, "Expecting a surface pattern"); + gfxIntSize sourceSize = source->GetSize(); + nsIntRect sourceRect(0, 0, sourceSize.width, sourceSize.height); + NS_ABORT_IF_FALSE(sourceRect == *aTileSourceRect, + "Cowardly refusing to create a temporary surface for tiling"); - /* Draw RGB surface onto frame */ - aContext->NewPath(); - // No need to snap here; our transform has already taken care of it. - aContext->Rectangle(gfxRect(0, 0, aSize.width, aSize.height)); - aContext->SetPattern(aPattern); - aContext->FillWithOpacity(aOpacity); + gfxContextAutoSaveRestore saveRestore(aContext); + + aContext->NewPath(); + gfxUtils::PathFromRegion(aContext, aVisible); + + aPattern->SetExtend(gfxPattern::EXTEND_REPEAT); + aContext->SetPattern(aPattern); + aContext->FillWithOpacity(aOpacity); + } + + // Reset extend mode for callers that need to reuse the pattern + aPattern->SetExtend(extend); } class BasicColorLayer : public ColorLayer, BasicImplData { @@ -1890,7 +1914,9 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, } nsRefPtr tmpCtx = new gfxContext(mBackSurface); - PaintContext(pat, mSize, 1.0, tmpCtx); + PaintContext(pat, + nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)), + nsnull, 1.0, tmpCtx); BasicManager()->PaintedImage(BasicManager()->Hold(this), mBackSurface); @@ -2366,7 +2392,8 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, nsRefPtr pat = new gfxPattern(mFrontSurface); pat->SetFilter(mFilter); - BasicImageLayer::PaintContext(pat, mSize, GetEffectiveOpacity(), aContext); + BasicImageLayer::PaintContext( + pat, GetEffectiveVisibleRegion(), GetTileSourceRect(), GetEffectiveOpacity(), aContext); } class BasicShadowColorLayer : public ShadowColorLayer, @@ -2631,6 +2658,8 @@ BasicShadowLayerManager::SetRoot(Layer* aLayer) void BasicShadowLayerManager::Mutated(Layer* aLayer) { + BasicLayerManager::Mutated(aLayer); + NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase"); if (HasShadowManager()) { ShadowLayerForwarder::Mutated(Hold(aLayer)); diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl index aa0732d8db3d..62b80fd146d1 100644 --- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -122,6 +122,8 @@ struct CommonLayerAttributes { float opacity; bool useClipRect; nsIntRect clipRect; + bool useTileSourceRect; + nsIntRect tileSourceRect; }; struct ThebesLayerAttributes { diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index eb63a3adfca0..6e051ed4cabc 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -345,6 +345,9 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray* aReplies) common.useClipRect() = !!mutant->GetClipRect(); common.clipRect() = (common.useClipRect() ? *mutant->GetClipRect() : nsIntRect()); + common.useTileSourceRect() = !!mutant->GetTileSourceRect(); + common.tileSourceRect() = (common.useTileSourceRect() ? + *mutant->GetTileSourceRect() : nsIntRect()); attrs.specific() = null_t(); mutant->FillSpecificAttributes(attrs.specific()); diff --git a/gfx/layers/ipc/ShadowLayersParent.cpp b/gfx/layers/ipc/ShadowLayersParent.cpp index 9c742047d183..b4c6f05e57ba 100644 --- a/gfx/layers/ipc/ShadowLayersParent.cpp +++ b/gfx/layers/ipc/ShadowLayersParent.cpp @@ -296,6 +296,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray& cset, layer->SetOpacity(common.opacity()); layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL); layer->SetTransform(common.transform()); + layer->SetTileSourceRect(common.useTileSourceRect() ? &common.tileSourceRect() : NULL); typedef SpecificLayerAttributes Specific; const SpecificLayerAttributes& specific = attrs.specific();