Index: trunk/Source/core/rendering/compositing/CompositedLayerMapping.cpp |
=================================================================== |
--- trunk/Source/core/rendering/compositing/CompositedLayerMapping.cpp (revision 168316) |
+++ trunk/Source/core/rendering/compositing/CompositedLayerMapping.cpp (working copy) |
@@ -346,7 +346,7 @@ |
{ |
// We need to know if we draw content in order to update our bounds (this has an effect |
// on whether or not descendands will paint into our backing). Update this value now. |
- updateDrawsContent(); |
+ updateDrawsContent(isSimpleContainerCompositingLayer()); |
LayoutRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); |
@@ -514,7 +514,7 @@ |
m_graphicsLayer->setReplicatedByLayer(0); |
} |
- updateBackgroundColor(); |
+ updateBackgroundColor(isSimpleContainerCompositingLayer()); |
if (isDirectlyCompositedImage()) |
updateImageContents(); |
@@ -632,6 +632,8 @@ |
if (!hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyOpacity)) |
updateOpacity(renderer()->style()); |
+ bool isSimpleContainer = isSimpleContainerCompositingLayer(); |
+ |
m_owningLayer->updateDescendantDependentFlags(); |
// m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing |
@@ -849,9 +851,9 @@ |
updateIsRootForIsolatedGroup(); |
} |
- updateContentsRect(); |
- updateBackgroundColor(); |
- updateDrawsContent(); |
+ updateContentsRect(isSimpleContainer); |
+ updateBackgroundColor(isSimpleContainer); |
+ updateDrawsContent(isSimpleContainer); |
updateContentsOpaque(); |
updateAfterWidgetResize(); |
updateRenderingContext(); |
@@ -936,12 +938,18 @@ |
} |
} |
-void CompositedLayerMapping::updateContentsRect() |
+void CompositedLayerMapping::updateContentsRect(bool isSimpleContainer) |
{ |
- m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox())); |
+ LayoutRect contentsRect; |
+ if (isSimpleContainer && renderer()->hasBackground()) |
+ contentsRect = backgroundBox(); |
+ else |
+ contentsRect = contentsBox(); |
+ |
+ m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsRect)); |
} |
-void CompositedLayerMapping::updateDrawsContent() |
+void CompositedLayerMapping::updateDrawsContent(bool isSimpleContainer) |
{ |
if (m_scrollingLayer) { |
// We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere. |
@@ -956,7 +964,7 @@ |
return; |
} |
- bool hasPaintedContent = containsPaintedContent(); |
+ bool hasPaintedContent = containsPaintedContent(isSimpleContainer); |
if (hasPaintedContent && isAcceleratedCanvas(renderer())) { |
CanvasRenderingContext* context = toHTMLCanvasElement(renderer()->node())->renderingContext(); |
// Content layer may be null if context is lost. |
@@ -1490,11 +1498,47 @@ |
return backgroundRenderer->resolveColor(CSSPropertyBackgroundColor); |
} |
-void CompositedLayerMapping::updateBackgroundColor() |
+void CompositedLayerMapping::updateBackgroundColor(bool isSimpleContainer) |
{ |
- m_graphicsLayer->setBackgroundColor(rendererBackgroundColor()); |
+ Color backgroundColor = rendererBackgroundColor(); |
+ if (isSimpleContainer) { |
+ m_graphicsLayer->setContentsToSolidColor(backgroundColor); |
+ m_graphicsLayer->setBackgroundColor(Color::transparent); |
+ } else { |
+ m_graphicsLayer->setContentsToSolidColor(Color::transparent); |
+ m_graphicsLayer->setBackgroundColor(backgroundColor); |
+ } |
} |
+static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer) |
+{ |
+ if (renderer->hasClip()) |
+ return false; |
+ |
+ if (hasBoxDecorationsOrBackgroundImage(renderer->style())) |
+ return false; |
+ |
+ // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now. |
+ if (renderer->style()->backgroundComposite() != CompositeSourceOver) |
+ return false; |
+ |
+ if (renderer->style()->backgroundClip() == TextFillBox) |
+ return false; |
+ |
+ return true; |
+} |
+ |
+bool CompositedLayerMapping::paintsBoxDecorations() const |
+{ |
+ if (!m_owningLayer->hasVisibleBoxDecorations()) |
+ return false; |
+ |
+ if (!supportsDirectBoxDecorationsComposition(renderer())) |
+ return true; |
+ |
+ return false; |
+} |
+ |
bool CompositedLayerMapping::paintsChildren() const |
{ |
if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers()) |
@@ -1511,6 +1555,52 @@ |
return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing(); |
} |
+// A "simple container layer" is a RenderLayer which has no visible content to render. |
+// It may have no children, or all its children may be themselves composited. |
+// This is a useful optimization, because it allows us to avoid allocating backing store. |
+bool CompositedLayerMapping::isSimpleContainerCompositingLayer() const |
+{ |
+ RenderObject* renderObject = renderer(); |
+ if (renderObject->hasMask()) // masks require special treatment |
+ return false; |
+ |
+ if (renderObject->isReplaced() && !isCompositedPlugin(renderObject)) |
+ return false; |
+ |
+ if (paintsBoxDecorations() || paintsChildren()) |
+ return false; |
+ |
+ if (renderObject->isRenderRegion()) |
+ return false; |
+ |
+ if (renderObject->node() && renderObject->node()->isDocumentNode()) { |
+ // Look to see if the root object has a non-simple background |
+ RenderObject* rootObject = renderObject->document().documentElement() ? renderObject->document().documentElement()->renderer() : 0; |
+ if (!rootObject) |
+ return false; |
+ |
+ RenderStyle* style = rootObject->style(); |
+ |
+ // Reject anything that has a border, a border-radius or outline, |
+ // or is not a simple background (no background, or solid color). |
+ if (hasBoxDecorationsOrBackgroundImage(style)) |
+ return false; |
+ |
+ // Now look at the body's renderer. |
+ HTMLElement* body = renderObject->document().body(); |
+ RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; |
+ if (!bodyObject) |
+ return false; |
+ |
+ style = bodyObject->style(); |
+ |
+ if (hasBoxDecorationsOrBackgroundImage(style)) |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
static bool hasVisibleNonCompositingDescendant(RenderLayer* parent) |
{ |
// FIXME: We shouldn't be called with a stale z-order lists. See bug 85512. |
@@ -1550,54 +1640,20 @@ |
return hasVisibleNonCompositingDescendant(m_owningLayer); |
} |
-bool CompositedLayerMapping::containsPaintedContent() const |
+bool CompositedLayerMapping::containsPaintedContent(bool isSimpleContainer) const |
{ |
- if (paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection()) |
+ if (isSimpleContainer || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection()) |
return false; |
if (isDirectlyCompositedImage()) |
return false; |
- RenderObject* renderObject = renderer(); |
// FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely, |
// and set background color on the layer in that case, instead of allocating backing store and painting. |
- if (renderObject->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo()) |
+ if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo()) |
return m_owningLayer->hasBoxDecorationsOrBackground(); |
- if (m_owningLayer->hasVisibleBoxDecorations()) |
- return true; |
- |
- if (renderObject->hasMask()) // masks require special treatment |
- return true; |
- |
- if (renderObject->isReplaced() && !isCompositedPlugin(renderObject)) |
- return true; |
- |
- if (renderObject->isRenderRegion()) |
- return true; |
- |
- if (renderObject->node() && renderObject->node()->isDocumentNode() && renderObject->document().documentElement()) { |
- // Look to see if the root object has a non-simple background |
- RenderObject* rootObject = renderObject->document().documentElement()->renderer(); |
- RenderStyle* style = rootObject->style(); |
- |
- // Reject anything that has a border, a border-radius or outline, |
- // or is not a simple background (no background, or solid color). |
- if (hasBoxDecorationsOrBackgroundImage(style)) |
- return true; |
- |
- // Now look at the body's renderer. |
- HTMLElement* body = renderObject->document().body(); |
- RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; |
- if (bodyObject) { |
- style = bodyObject->style(); |
- if (hasBoxDecorationsOrBackgroundImage(style)) |
- return true; |
- } |
- } |
- |
- // FIXME: it's O(n^2). A better solution is needed. |
- return paintsChildren(); |
+ return true; |
} |
// An image can be directly compositing if it's the sole content of the layer, and has no box decorations |
@@ -1653,7 +1709,8 @@ |
// This is a no-op if the layer doesn't have an inner layer for the image. |
m_graphicsLayer->setContentsToImage(image); |
- updateDrawsContent(); |
+ bool isSimpleContainer = false; |
+ updateDrawsContent(isSimpleContainer); |
// Image animation is "lazy", in that it automatically stops unless someone is drawing |
// the image. So we have to kick the animation each time; this has the downside that the |
@@ -1700,6 +1757,13 @@ |
return contentsBox; |
} |
+IntRect CompositedLayerMapping::backgroundBox() const |
+{ |
+ LayoutRect backgroundBox = backgroundRect(renderer()); |
+ backgroundBox.move(contentOffsetInCompostingLayer()); |
+ return pixelSnappedIntRect(backgroundBox); |
+} |
+ |
GraphicsLayer* CompositedLayerMapping::parentForSublayers() const |
{ |
if (m_scrollingContentsLayer) |