Bug 539356 - Part 5 - Change SVG effects painting to use a LayerManager transaction. r=roc

This commit is contained in:
Matt Woodrow 2012-07-17 13:03:51 -04:00
parent 66f1cdb4bc
commit 0794dcd107
6 changed files with 84 additions and 20 deletions

View File

@ -1564,7 +1564,8 @@ DumpPaintedImage(nsDisplayItem* aItem, gfxASurface* aSurf)
static void
PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
gfxContext* aContext)
gfxContext* aContext,
nsRenderingContext* aCtx)
{
// This item has an inactive layer. Render it to a ThebesLayer
// using a temporary BasicLayerManager.
@ -1595,7 +1596,11 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
tempManager->SetRoot(layer);
aBuilder->LayerBuilder()->WillEndTransaction(tempManager);
tempManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
static_cast<nsDisplaySVGEffects*>(aItem)->PaintAsLayer(aBuilder, aCtx, tempManager);
} else {
tempManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
}
aBuilder->LayerBuilder()->DidEndTransaction(tempManager);
#ifdef MOZ_DUMP_PAINTING
@ -2572,7 +2577,7 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
}
if (cdi->mInactiveLayer) {
PaintInactiveLayer(builder, cdi->mItem, aContext);
PaintInactiveLayer(builder, cdi->mItem, aContext, rc);
} else {
nsIFrame* frame = cdi->mItem->GetUnderlyingFrame();
if (frame) {

View File

@ -29,7 +29,9 @@ enum LayerState {
// when the layer has rounded rect clips.
LAYER_ACTIVE_FORCE,
// Special layer that is metadata only.
LAYER_ACTIVE_EMPTY
LAYER_ACTIVE_EMPTY,
// Inactive style layer for rendering SVG effects.
LAYER_SVG_EFFECTS
};
class RefCountedRegion : public RefCounted<RefCountedRegion> {

View File

@ -3256,11 +3256,52 @@ nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect
}
}
void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
void
nsDisplaySVGEffects::PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager)
{
nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx,
mFrame, mVisibleRect, aBuilder, &mList);
nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx, mFrame,
mVisibleRect,
aBuilder, aManager);
}
LayerState
nsDisplaySVGEffects::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aParameters)
{
return LAYER_SVG_EFFECTS;
}
already_AddRefed<Layer>
nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aContainerParameters)
{
float opacity = mFrame->GetStyleDisplay()->mOpacity;
if (opacity == 0.0f)
return nsnull;
nsIFrame* firstFrame =
nsLayoutUtils::GetFirstContinuationOrSpecialSibling(mFrame);
nsSVGEffects::EffectProperties effectProperties =
nsSVGEffects::GetEffectProperties(firstFrame);
bool isOK = true;
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
nsSVGMaskFrame *maskFrame = effectProperties.GetMaskFrame(&isOK);
nsSVGFilterFrame *filterFrame = effectProperties.GetFilterFrame(&isOK);
if (!isOK) {
return nsnull;
}
nsRefPtr<ContainerLayer> container = aBuilder->LayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
aContainerParameters, nsnull);
return container.forget();
}
bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,

View File

@ -2173,13 +2173,24 @@ public:
*aSnap = false;
return mEffectsBounds + ToReferenceFrame();
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aParameters);
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aContainerParameters);
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx,
LayerManager* aManager);
#ifdef MOZ_DUMP_PAINTING
void PrintEffects(FILE* aOutput);
#endif

View File

@ -18,6 +18,11 @@
#include "nsSVGMaskFrame.h"
#include "nsSVGPaintServerFrame.h"
#include "nsSVGUtils.h"
#include "FrameLayerBuilder.h"
#include "BasicLayers.h"
using namespace mozilla;
using namespace mozilla::layers;
// ----------------------------------------------------------------------
@ -341,23 +346,23 @@ class RegularFramePaintCallback : public nsSVGFilterPaintCallback
{
public:
RegularFramePaintCallback(nsDisplayListBuilder* aBuilder,
nsDisplayList* aInnerList,
nsIFrame* aFrame,
LayerManager* aManager,
const nsPoint& aOffset)
: mBuilder(aBuilder), mInnerList(aInnerList), mFrame(aFrame),
: mBuilder(aBuilder), mLayerManager(aManager),
mOffset(aOffset) {}
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect* aDirtyRect)
{
BasicLayerManager* basic = static_cast<BasicLayerManager*>(mLayerManager);
basic->SetTarget(aContext->ThebesContext());
nsRenderingContext::AutoPushTranslation push(aContext, -mOffset);
mInnerList->PaintForFrame(mBuilder, aContext, mFrame, nsDisplayList::PAINT_DEFAULT);
mLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, mBuilder);
}
private:
nsDisplayListBuilder* mBuilder;
nsDisplayList* mInnerList;
nsIFrame* mFrame;
LayerManager* mLayerManager;
nsPoint mOffset;
};
@ -366,7 +371,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
nsIFrame* aFrame,
const nsRect& aDirtyRect,
nsDisplayListBuilder* aBuilder,
nsDisplayList* aInnerList)
LayerManager *aLayerManager)
{
#ifdef DEBUG
nsISVGChildFrame *svgChildFrame = do_QueryFrame(aFrame);
@ -442,14 +447,13 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
/* Paint the child */
if (filterFrame) {
RegularFramePaintCallback callback(aBuilder, aInnerList, aFrame,
RegularFramePaintCallback callback(aBuilder, aLayerManager,
offset);
nsRect dirtyRect = aDirtyRect - offset;
filterFrame->PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect);
} else {
gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
aInnerList->PaintForFrame(aBuilder, aCtx, aFrame,
nsDisplayList::PAINT_DEFAULT);
aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
aCtx->Translate(offset);
}

View File

@ -10,6 +10,7 @@
#include "gfxPattern.h"
#include "gfxRect.h"
#include "nsRect.h"
#include "Layers.h"
class nsDisplayList;
class nsDisplayListBuilder;
@ -134,7 +135,7 @@ public:
PaintFramesWithEffects(nsRenderingContext* aCtx,
nsIFrame* aFrame, const nsRect& aDirtyRect,
nsDisplayListBuilder* aBuilder,
nsDisplayList* aInnerList);
mozilla::layers::LayerManager* aManager);
/**
* SVG frames expect to paint in SVG user units, which are equal to CSS px