提交 0be786f6 编写于 作者: O Ojan Vafai

Simplify and reduce calls to beginTransparencyLayers.

-Consolidate the beginTransparencyLayers calls. The call
on layer()->parent() was just not needed as best I can tell
and the filter one could just be shared with the non-filter
codepath. FWIW, blink has already made a similar set of changes.
-Don't walk up the tree calling beginTransparencyLayer.
We're doing this in a recursive call down, so we've already
created the transparency layer for any transparent ancestors.
-Remove unused TransparencyClipBoxMode argument.
-Inline the paintingExtent method.
-Removed unused REVEAL_TRANSPARENCY_LAYERS #define.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/959543002
上级 ab273a84
......@@ -58,12 +58,10 @@ struct LayerPaintingInfo {
: rootLayer(inRootLayer)
, paintDirtyRect(inDirtyRect)
, subPixelAccumulation(inSubPixelAccumulation)
, clipToDirtyRect(true)
{ }
RenderLayer* rootLayer;
LayoutRect paintDirtyRect; // relative to rootLayer;
LayoutSize subPixelAccumulation;
bool clipToDirtyRect;
};
} // namespace blink
......
......@@ -710,12 +710,6 @@ void RenderBox::paintLayer(GraphicsContext* context, RenderLayer* rootLayer, con
if (!layerTransform->isInvertible())
return;
// If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
// layer from the parent now, assuming there is a parent
if (layer()->isTransparent()) {
layer()->parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
}
// Make sure the parent's clip rects have been calculated.
ClipRectsContext clipRectsContext(paintingInfo.rootLayer, PaintingClipRects);
ClipRect clipRect = layer()->clipper().backgroundClipRect(clipRectsContext);
......@@ -754,8 +748,6 @@ void RenderBox::paintLayerContents(GraphicsContext* context, const LayerPainting
float deviceScaleFactor = blink::deviceScaleFactor(frame());
context->setDeviceScaleFactor(deviceScaleFactor);
GraphicsContext* transparencyLayerContext = context;
LayoutPoint offsetFromRoot;
layer()->convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
......@@ -798,7 +790,10 @@ void RenderBox::paintLayerContents(GraphicsContext* context, const LayerPainting
}
}
bool haveTransparency = layer()->isTransparent();
if (layer()->isTransparent())
layer()->beginTransparencyLayers(context, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, localPaintingInfo.subPixelAccumulation);
layer()->clipToRect(localPaintingInfo, context, contentRect);
FilterEffectRendererHelper filterPainter(layer()->filterRenderer() && layer()->paintsWithFilters());
......@@ -808,39 +803,12 @@ void RenderBox::paintLayerContents(GraphicsContext* context, const LayerPainting
if (!rootRelativeBoundsComputed)
rootRelativeBounds = layer()->physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
if (filterPainter.prepareFilterEffect(layer(), rootRelativeBounds, paintingInfo.paintDirtyRect)) {
// Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
// NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
// on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that
// beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method.
// With deferred filters, we don't need a separate context, but we do need to do transparency and clipping before starting
// filter processing.
// FIXME: when the legacy path is removed, remove the transparencyLayerContext as well.
if (haveTransparency) {
// If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one after filter processing.
layer()->beginTransparencyLayers(context, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
}
// We'll handle clipping to the dirty rect before filter rasterization.
// Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets.
// FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
layer()->clipToRect(localPaintingInfo, context, contentRect);
// Subsequent code should not clip to the dirty rect, since we've already
// done it above, and doing it later will defeat the outsets.
localPaintingInfo.clipToDirtyRect = false;
if (filterPainter.prepareFilterEffect(layer(), rootRelativeBounds, paintingInfo.paintDirtyRect))
context = filterPainter.beginFilterEffect(context);
}
}
LayoutPoint layerLocation = toPoint(layerBounds.location() - location() + localPaintingInfo.subPixelAccumulation);
// Begin transparency if we have something to paint.
if (haveTransparency)
layer()->beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, localPaintingInfo.subPixelAccumulation);
if (localPaintingInfo.clipToDirtyRect)
layer()->clipToRect(localPaintingInfo, context, contentRect);
Vector<RenderBox*> layers;
PaintInfo paintInfo(context, pixelSnappedIntRect(contentRect.rect()), localPaintingInfo.rootLayer->renderer());
paint(paintInfo, layerLocation, layers);
......@@ -850,22 +818,14 @@ void RenderBox::paintLayerContents(GraphicsContext* context, const LayerPainting
box->paintLayer(context, paintingInfo.rootLayer, rect);
}
if (localPaintingInfo.clipToDirtyRect)
layer()->restoreClip(context, localPaintingInfo.paintDirtyRect, contentRect);
if (filterPainter.hasStartedFilterEffect()) {
if (filterPainter.hasStartedFilterEffect())
context = filterPainter.applyFilterEffect();
layer()->restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, contentRect);
}
// Make sure that we now use the original transparency context.
ASSERT(transparencyLayerContext == context);
layer()->restoreClip(context, localPaintingInfo.paintDirtyRect, contentRect);
// End our transparency layer
if (haveTransparency && layer()->usedTransparency()) {
if (layer()->isTransparent()) {
context->endLayer();
context->restore();
layer()->clearUsedTransparency();
}
}
......
......@@ -83,7 +83,6 @@ RenderLayer::RenderLayer(RenderBox* renderer, LayerType type)
, m_hasSelfPaintingLayerDescendant(false)
, m_hasSelfPaintingLayerDescendantDirty(false)
, m_isRootLayer(renderer->isRenderView())
, m_usedTransparency(false)
, m_3DTransformedDescendantStatusDirty(true)
, m_has3DTransformedDescendant(false)
, m_hasFilterInfo(false)
......@@ -411,45 +410,30 @@ bool RenderLayer::hasAncestorWithFilterOutsets() const
return false;
}
RenderLayer* RenderLayer::transparentPaintingAncestor()
{
for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
if (curr->isTransparent())
return curr;
}
return 0;
}
enum TransparencyClipBoxBehavior {
PaintingTransparencyClipBox,
HitTestingTransparencyClipBox
};
enum TransparencyClipBoxMode {
DescendantsOfTransparencyClipBox,
RootOfTransparencyClipBox
};
static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, const LayoutSize& subPixelAccumulation);
static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, const LayoutSize& subPixelAccumulation);
static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer,
TransparencyClipBoxBehavior transparencyBehavior, const LayoutSize& subPixelAccumulation)
const LayoutSize& subPixelAccumulation)
{
// Note: we don't have to walk z-order lists since transparent elements always establish
// a stacking container. This means we can just walk the layer tree directly.
for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling())
clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, subPixelAccumulation));
clipRect.unite(transparencyClipBox(curr, rootLayer, subPixelAccumulation));
}
static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation)
static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer,
const LayoutSize& subPixelAccumulation)
{
// FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
// paintDirtyRect, and that should cut down on the amount we have to paint. Still it
// would be better to respect clips.
if (rootLayer != layer && ((transparencyBehavior == PaintingTransparencyClipBox && layer->transform())
|| (transparencyBehavior == HitTestingTransparencyClipBox && layer->hasTransform()))) {
if (rootLayer != layer && layer->transform()) {
// The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
// the transformed layer and all of its children.
const RenderLayer* rootLayerForTransform = rootLayer;
......@@ -463,48 +447,29 @@ static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLaye
transform = transform * *layer->transform();
// We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
// paints unfragmented.
// paints unfragmented.y
LayoutRect clipRect = layer->physicalBoundingBox(layer);
expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, subPixelAccumulation);
expandClipRectForDescendantsAndReflection(clipRect, layer, layer, subPixelAccumulation);
layer->renderer()->style()->filterOutsets().expandRect(clipRect);
LayoutRect result = transform.mapRect(clipRect);
return result;
}
LayoutRect clipRect = layer->physicalBoundingBox(rootLayer);
expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, subPixelAccumulation);
expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, subPixelAccumulation);
layer->renderer()->style()->filterOutsets().expandRect(clipRect);
clipRect.move(subPixelAccumulation);
return clipRect;
}
LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation)
{
return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, subPixelAccumulation), paintDirtyRect);
}
void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation)
{
if (isTransparent() && m_usedTransparency)
return;
RenderLayer* ancestor = transparentPaintingAncestor();
if (ancestor)
ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, subPixelAccumulation);
if (isTransparent()) {
m_usedTransparency = true;
context->save();
LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation);
context->clip(clipRect);
context->beginTransparencyLayer(renderer()->opacity());
#ifdef REVEAL_TRANSPARENCY_LAYERS
context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
context->fillRect(clipRect);
#endif
}
ASSERT(isTransparent());
context->save();
LayoutRect clipRect = intersection(paintDirtyRect,
transparencyClipBox(this, rootLayer, subPixelAccumulation));
context->clip(clipRect);
context->beginTransparencyLayer(renderer()->opacity());
}
void* RenderLayer::operator new(size_t sz)
......
......@@ -131,9 +131,6 @@ public:
// True if this layer container renderers that paint.
bool hasNonEmptyChildRenderers() const;
bool usedTransparency() const { return m_usedTransparency; }
void clearUsedTransparency() { m_usedTransparency = false; }
// Gets the nearest enclosing positioned ancestor layer (also includes
// the <html> layer and the root layer).
RenderLayer* enclosingPositionedAncestor() const;
......@@ -267,8 +264,6 @@ private:
void updateOrRemoveFilterClients();
LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation);
LayerType m_layerType;
// Self-painting layer is an optimization where we avoid the heavy RenderLayer painting
......@@ -283,10 +278,6 @@ private:
const unsigned m_isRootLayer : 1;
unsigned m_usedTransparency : 1; // Tracks whether we need to close a transparent layer, i.e., whether
// we ended up painting this layer or any descendants (and therefore need to
// blend).
unsigned m_3DTransformedDescendantStatusDirty : 1;
// Set on a stacking context layer that has 3D descendants anywhere
// in a preserves3D hierarchy. Hint to do 3D-aware hit testing.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册