WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch, changelog
23357_patch2.txt (text/plain), 85.13 KB, created by
Simon Fraser (smfr)
on 2009-01-23 16:22:41 PST
(
hide
)
Description:
Patch, changelog
Filename:
MIME Type:
Creator:
Simon Fraser (smfr)
Created:
2009-01-23 16:22:41 PST
Size:
85.13 KB
patch
obsolete
>diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog >index ba5bc9e..e20936d 100644 >--- a/WebCore/ChangeLog >+++ b/WebCore/ChangeLog >@@ -1,3 +1,25 @@ >+2009-01-23 Simon Fraser <simon.fraser@apple.com> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ https://bugs.webkit.org/show_bug.cgi?id=23357 >+ >+ New files to support accelerated compositing at the RenderLayer >+ level. >+ >+ * WebCore.xcodeproj/project.pbxproj: >+ New files added to project. >+ >+ * rendering/RenderLayerBacking.cpp: Added. >+ * rendering/RenderLayerBacking.h: Added. >+ New object to store compositing-related data for a single >+ RenderLayer. >+ >+ * rendering/RenderLayerCompositor.cpp: Added. >+ * rendering/RenderLayerCompositor.h: Added. >+ Per-RenderView controller object for compositing hierarchy >+ maintenance. >+ > 2009-01-23 David Hyatt <hyatt@apple.com> > > Fix for <rdar://problem/6518850> REGRESSION: hover feedback not showing on many sites >diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj >index f0857d7..ad3d3c4 100644 >--- a/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -139,6 +139,10 @@ > 0F5602900E4B76580065B038 /* RenderMarquee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56028E0E4B76580065B038 /* RenderMarquee.cpp */; }; > 0F6ECD450F252F3700BDE271 /* CSSPropertyLonghand.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6ECD430F252F3700BDE271 /* CSSPropertyLonghand.h */; }; > 0F6ECD460F252F3700BDE271 /* CSSPropertyLonghand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6ECD440F252F3700BDE271 /* CSSPropertyLonghand.cpp */; }; >+ 0FAFF9AE0F2A96910007DB75 /* RenderLayerCompositor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FAFF9AA0F2A96910007DB75 /* RenderLayerCompositor.h */; }; >+ 0FAFF9AF0F2A96910007DB75 /* RenderLayerCompositor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FAFF9AB0F2A96910007DB75 /* RenderLayerCompositor.cpp */; }; >+ 0FAFF9B00F2A96910007DB75 /* RenderLayerBacking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FAFF9AC0F2A96910007DB75 /* RenderLayerBacking.h */; }; >+ 0FAFF9B10F2A96910007DB75 /* RenderLayerBacking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FAFF9AD0F2A96910007DB75 /* RenderLayerBacking.cpp */; }; > 0FC705210EB1815600B90AD8 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC705200EB1815600B90AD8 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FD723820EC8BD9300CA5DD7 /* FloatQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0FD723830EC8BD9300CA5DD7 /* FloatQuad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */; }; >@@ -4975,6 +4979,10 @@ > 0F56028E0E4B76580065B038 /* RenderMarquee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMarquee.cpp; sourceTree = "<group>"; }; > 0F6ECD430F252F3700BDE271 /* CSSPropertyLonghand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPropertyLonghand.h; sourceTree = "<group>"; }; > 0F6ECD440F252F3700BDE271 /* CSSPropertyLonghand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertyLonghand.cpp; sourceTree = "<group>"; }; >+ 0FAFF9AA0F2A96910007DB75 /* RenderLayerCompositor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderLayerCompositor.h; sourceTree = "<group>"; }; >+ 0FAFF9AB0F2A96910007DB75 /* RenderLayerCompositor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerCompositor.cpp; sourceTree = "<group>"; }; >+ 0FAFF9AC0F2A96910007DB75 /* RenderLayerBacking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderLayerBacking.h; sourceTree = "<group>"; }; >+ 0FAFF9AD0F2A96910007DB75 /* RenderLayerBacking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerBacking.cpp; sourceTree = "<group>"; }; > 0FC705200EB1815600B90AD8 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicStringHash.h; sourceTree = "<group>"; }; > 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatQuad.h; sourceTree = "<group>"; }; > 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatQuad.cpp; sourceTree = "<group>"; }; >@@ -14051,6 +14059,10 @@ > BCEA4839097D93020094C9E4 /* RenderInline.h */, > BCEA483A097D93020094C9E4 /* RenderLayer.cpp */, > BCEA483B097D93020094C9E4 /* RenderLayer.h */, >+ 0FAFF9AD0F2A96910007DB75 /* RenderLayerBacking.cpp */, >+ 0FAFF9AC0F2A96910007DB75 /* RenderLayerBacking.h */, >+ 0FAFF9AB0F2A96910007DB75 /* RenderLayerCompositor.cpp */, >+ 0FAFF9AA0F2A96910007DB75 /* RenderLayerCompositor.h */, > A8EA73B60A1900E300A8EF5F /* RenderLegend.cpp */, > A8EA73BD0A1900E300A8EF5F /* RenderLegend.h */, > ABB5419C0ACDDFE4002820EB /* RenderListBox.cpp */, >@@ -16628,6 +16640,8 @@ > 1A569D250D7E2B82007C3983 /* runtime_root.h in Headers */, > 93309E1E099E64920056E581 /* visible_units.h in Headers */, > 18A0537D0F26859C00A51705 /* WorkerRunLoop.h in Headers */, >+ 0FAFF9AE0F2A96910007DB75 /* RenderLayerCompositor.h in Headers */, >+ 0FAFF9B00F2A96910007DB75 /* RenderLayerBacking.h in Headers */, > ); > runOnlyForDeploymentPostprocessing = 0; > }; >@@ -18597,6 +18611,8 @@ > 1A569D220D7E2B82007C3983 /* runtime_object.cpp in Sources */, > 1A569D240D7E2B82007C3983 /* runtime_root.cpp in Sources */, > 93309E1D099E64920056E581 /* visible_units.cpp in Sources */, >+ 0FAFF9AF0F2A96910007DB75 /* RenderLayerCompositor.cpp in Sources */, >+ 0FAFF9B10F2A96910007DB75 /* RenderLayerBacking.cpp in Sources */, > ); > runOnlyForDeploymentPostprocessing = 0; > }; >diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp >new file mode 100644 >index 0000000..ced1cf8 >--- /dev/null >+++ b/WebCore/rendering/RenderLayerBacking.cpp >@@ -0,0 +1,951 @@ >+/* >+ * Copyright (C) 2009 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+ >+#if USE(ACCELERATED_COMPOSITING) >+ >+#include "AnimationController.h" >+#include "CSSStyleSelector.h" >+#include "FrameView.h" >+#include "GraphicsContext.h" >+#include "GraphicsLayer.h" >+#include "HitTestRequest.h" >+#include "HitTestResult.h" >+#include "HTMLNames.h" >+#include "RenderBox.h" >+#include "RenderImage.h" >+#include "RenderLayerCompositor.h" >+#include "RenderVideo.h" >+#include "RenderView.h" >+ >+#include "RenderLayerBacking.h" >+ >+using namespace std; >+ >+namespace WebCore { >+ >+struct LayerHitTestData { >+ LayerHitTestData(RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& hitTestResult, const IntRect& hitTestRect) >+ : m_rootLayer(rootLayer) >+ , m_request(request) >+ , m_hitTestRect(hitTestRect) >+ , m_result(hitTestResult) >+ { >+ } >+ >+ RenderLayer* m_rootLayer; >+ const HitTestRequest& m_request; >+ const IntRect& m_hitTestRect; >+ HitTestResult& m_result; >+}; >+ >+ >+RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) >+ : m_owningLayer(layer) >+ , m_ancestorClippingLayer(0) >+ , m_graphicsLayer(0) >+ , m_contentsLayer(0) >+ , m_clippingLayer(0) >+ , m_forceCompositingLayer(false) >+ , m_isSimpleContainerCompositingLayer(false) >+ , m_simpleCompositingLayerStatusDirty(true) >+ , m_compositingContentOffsetDirty(true) >+{ >+ createGraphicsLayer(); >+} >+ >+RenderLayerBacking::~RenderLayerBacking() >+{ >+ updateClippingLayers(false, false); >+ updateContentsLayer(false); >+ destroyGraphicsLayer(); >+} >+ >+void RenderLayerBacking::createGraphicsLayer() >+{ >+ m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this); >+ >+#ifndef NDEBUG >+ if (renderer()->node()->isDocumentNode()) >+ m_graphicsLayer->setName("Document Node"); >+ else { >+ if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID()) >+ m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->element())->id()); >+ else >+ m_graphicsLayer->setName(renderer()->renderName()); >+ } >+#endif // NDEBUG >+ >+ updateLayerOpacity(); >+ updateLayerTransform(); >+} >+ >+void RenderLayerBacking::destroyGraphicsLayer() >+{ >+ if (m_graphicsLayer) >+ m_graphicsLayer->removeFromParent(); >+ >+ delete m_graphicsLayer; >+ m_graphicsLayer = 0; >+ >+ delete m_contentsLayer; >+ m_contentsLayer = 0; >+ >+ delete m_clippingLayer; >+ m_clippingLayer = 0; >+} >+ >+void RenderLayerBacking::updateLayerOpacity() >+{ >+ m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()), 0, 0); >+} >+ >+void RenderLayerBacking::updateLayerTransform() >+{ >+ RenderStyle* style = renderer()->style(); >+ const IntRect borderBox = renderer()->borderBoxRect(); >+ >+ // FIXME: This should use m_owningLayer->transform(), but that currently has transform-origin >+ // baked into it, and we don't want that. >+ TransformationMatrix t; >+ style->applyTransform(t, borderBox.size(), false); >+ >+ m_graphicsLayer->setTransform(t); >+} >+ >+void RenderLayerBacking::updateAfterLayout() >+{ >+ invalidateDrawingOptimizations(); >+ detectDrawingOptimizations(); >+ >+ updateGraphicsLayerGeometry(); >+} >+ >+bool RenderLayerBacking::updateGraphicsLayers(bool needsContentsLayer, bool needsUpperClippingLayer, bool needsLowerClippingLayer, bool needsRepaint) >+{ >+ bool layerConfigChanged = false; >+ if (updateContentsLayer(needsContentsLayer)) >+ layerConfigChanged = true; >+ >+ if (updateClippingLayers(needsUpperClippingLayer, needsLowerClippingLayer)) >+ layerConfigChanged = true; >+ >+ // See if we can now use any drawing optimizations. >+ bool didDrawContent = graphicsLayer()->drawsContent(); >+ invalidateDrawingOptimizations(); >+ detectDrawingOptimizations(); >+ if (!didDrawContent && graphicsLayer()->drawsContent()) >+ needsRepaint = true; >+ >+ // Set opacity, if it is not animating. >+ if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity)) >+ updateLayerOpacity(); >+ >+ updateGraphicsLayerGeometry(); >+ >+ m_graphicsLayer->updateContentsRect(); >+ >+ if (needsRepaint) { >+ m_graphicsLayer->setNeedsDisplay(); >+ if (m_contentsLayer) >+ m_contentsLayer->setNeedsDisplay(); >+ } >+ >+ return layerConfigChanged; >+} >+ >+void RenderLayerBacking::updateGraphicsLayerGeometry() >+{ >+ // If we haven't built z-order lists yet, wait until later. >+ if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty) >+ return; >+ >+ // Set transform property, if it is not animating. We have to do this here because the transform >+ // is affected by the layer dimensions. >+ if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform)) >+ updateLayerTransform(); >+ >+ m_compositingContentOffsetDirty = true; >+ >+ RenderLayer* compAncestor = compositor()->enclosingCompositingLayer(m_owningLayer, false); >+ >+ // We compute everything relative to the enclosing compositing layer. >+ IntRect ancestorCompositingBounds; >+ if (compAncestor) >+ ancestorCompositingBounds = compositor()->calculateCompositedBounds(compAncestor, compAncestor); >+ >+ IntRect localCompositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); >+ >+ IntRect relativeCompositingBounds(localCompositingBounds); >+ int deltaX = 0, deltaY = 0; >+ m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY); >+ relativeCompositingBounds.move(deltaX, deltaY); >+ >+ IntPoint graphicsLayerParentLocation; >+ if (compAncestor && compAncestor->backing()->hasClippingLayer()) { >+ // If the compositing ancestor has a layer to clip children, we parent in that, and therefore >+ // position relative to it. >+ graphicsLayerParentLocation = compAncestor->renderer()->getOverflowClipRect(0, 0).location(); >+ } else >+ graphicsLayerParentLocation = ancestorCompositingBounds.location(); >+ >+ if (compAncestor && m_ancestorClippingLayer) { >+ // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this >+ // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects >+ // for a compositing layer, rootLayer is the layer itself. >+ IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX); >+ IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; >+ m_owningLayer->calculateRects(compAncestor, infiniteRect, layerBounds, backgroundRect, foregroundRect, outlineRect, true); >+ >+ m_ancestorClippingLayer->setPosition(FloatPoint() + (backgroundRect.location() - graphicsLayerParentLocation)); >+ m_ancestorClippingLayer->setSize(backgroundRect.size()); >+ >+ // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. >+ IntSize rendererOffset(backgroundRect.location().x() - deltaX, backgroundRect.location().y() - deltaY); >+ m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset); >+ >+ // The primary layer is then parented in, and positioned relative to this clipping layer. >+ graphicsLayerParentLocation = backgroundRect.location(); >+ } >+ >+ m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation)); >+ m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint()); >+ >+ FloatSize oldSize = m_graphicsLayer->size(); >+ FloatSize newSize = relativeCompositingBounds.size(); >+ if (oldSize != newSize) { >+ m_graphicsLayer->setSize(newSize); >+ // A bounds change will almost always require redisplay. Usually that redisplay >+ // will happen because of a repaint elsewhere, but not always: >+ // e.g. see RenderView::setMaximalOutlineSize() >+ m_graphicsLayer->setNeedsDisplay(); >+ } >+ >+ // If we have a layer that clips children, position it. >+ if (m_clippingLayer) { >+ IntRect clippingBox = renderer()->getOverflowClipRect(0, 0); >+ m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location())); >+ m_clippingLayer->setSize(clippingBox.size()); >+ m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint()); >+ } >+ >+ IntRect layerBounds = IntRect(m_owningLayer->xPos(), m_owningLayer->yPos(), renderer()->width(), renderer()->height()); >+ >+ // Convert to absolute coords to match bbox. >+ int x = 0, y = 0; >+ m_owningLayer->convertToLayerCoords(compAncestor, x, y); >+ layerBounds.move(x - m_owningLayer->xPos(), y - m_owningLayer->yPos()); >+ >+ // Update properties that depend on layer dimensions >+ const IntRect borderBox = renderer()->borderBoxRect(); >+ >+ FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); >+ // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set. >+ FloatPoint anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f, >+ relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f); >+ m_graphicsLayer->setAnchorPoint(anchor, transformOrigin.z()); >+ >+ if (m_contentsLayer) { >+ // The contents layer is always coincidental with the graphicsLayer for now. >+ m_contentsLayer->setPosition(IntPoint(0, 0)); >+ m_contentsLayer->setSize(newSize); >+ m_contentsLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); >+ } >+ >+ m_graphicsLayer->updateContentsRect(); >+} >+ >+void RenderLayerBacking::updateInternalHierarchy() >+{ >+ // m_contentsLayer has to be inserted in the correct order with child layers, >+ // so it's not inserted here. >+ if (m_ancestorClippingLayer) { >+ m_ancestorClippingLayer->removeAllChildren(); >+ m_graphicsLayer->removeFromParent(); >+ m_ancestorClippingLayer->addChild(m_graphicsLayer); >+ } >+ >+ if (m_clippingLayer) { >+ m_clippingLayer->removeFromParent(); >+ m_graphicsLayer->addChild(m_clippingLayer); >+ } >+} >+ >+// Return true if the layers changed. >+bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip) >+{ >+ bool layersChanged = false; >+ >+ if (needsAncestorClip) { >+ if (!m_ancestorClippingLayer) { >+ m_ancestorClippingLayer = GraphicsLayer::createGraphicsLayer(this); >+#ifndef NDEBUG >+ m_ancestorClippingLayer->setName("Ancestor clipping Layer"); >+#endif >+ m_ancestorClippingLayer->setMasksToBounds(true); >+ layersChanged = true; >+ } >+ } else if (m_ancestorClippingLayer) { >+ m_ancestorClippingLayer->removeFromParent(); >+ delete m_ancestorClippingLayer; >+ m_ancestorClippingLayer = 0; >+ layersChanged = true; >+ } >+ >+ if (needsDescendantClip) { >+ if (!m_clippingLayer) { >+ m_clippingLayer = GraphicsLayer::createGraphicsLayer(0); >+#ifndef NDEBUG >+ m_clippingLayer->setName("Child clipping Layer"); >+#endif >+ m_clippingLayer->setMasksToBounds(true); >+ layersChanged = true; >+ } >+ } else if (m_clippingLayer) { >+ m_clippingLayer->removeFromParent(); >+ delete m_clippingLayer; >+ m_clippingLayer = 0; >+ layersChanged = true; >+ } >+ >+ if (layersChanged) >+ updateInternalHierarchy(); >+ >+ return layersChanged; >+} >+ >+bool RenderLayerBacking::updateContentsLayer(bool needsContentsLayer) >+{ >+ bool layerChanged = false; >+ if (needsContentsLayer) { >+ if (!m_contentsLayer) { >+ m_contentsLayer = GraphicsLayer::createGraphicsLayer(this); >+#ifndef NDEBUG >+ m_contentsLayer->setName("Contents"); >+#endif >+ m_contentsLayer->setDrawsContent(true); >+ m_contentsLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask); >+ m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask); >+ layerChanged = true; >+ } >+ } else if (m_contentsLayer) { >+ m_contentsLayer->removeFromParent(); >+ delete m_contentsLayer; >+ m_contentsLayer = 0; >+ m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask); >+ layerChanged = true; >+ } >+ return layerChanged; >+} >+ >+float RenderLayerBacking::compositingOpacity(float rendererOpacity) const >+{ >+ float finalOpacity = rendererOpacity; >+ >+ for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) { >+ // We only care about parents that are stacking contexts. >+ // Recall that opacity creates stacking context. >+ if (!curr->isStackingContext()) >+ continue; >+ >+ // If we found a compositing layer, we want to compute opacity >+ // relative to it. So we can break here. >+ if (curr->isComposited()) >+ break; >+ >+ finalOpacity *= curr->renderer()->opacity(); >+ } >+ >+ return finalOpacity; >+} >+ >+// A simple background is either none or a solid color. >+static bool hasSimpleBackground(RenderStyle* style) >+{ >+ return !style->hasBackgroundImage(); >+} >+ >+static bool hasBorderOutlineOrShadow(RenderStyle* style) >+{ >+ return (style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || (style->boxShadow() != 0)); >+} >+ >+bool RenderLayerBacking::rendererHasBackground() const >+{ >+ // FIXME: share more code here >+ if (renderer()->node()->isDocumentNode()) { >+ RenderObject* htmlObject = renderer()->firstChild(); >+ if (!htmlObject) >+ return false; >+ >+ RenderStyle* style = htmlObject->style(); >+ if (style->hasBackground()) >+ return true; >+ >+ RenderObject* bodyObject = htmlObject->firstChild(); >+ if (!bodyObject) >+ return false; >+ >+ style = bodyObject->style(); >+ return style->hasBackground(); >+ } >+ >+ return renderer()->style()->hasBackground(); >+} >+ >+const Color& RenderLayerBacking::rendererBackgroundColor() const >+{ >+ // FIXME: share more code here >+ if (renderer()->node()->isDocumentNode()) { >+ RenderObject* htmlObject = renderer()->firstChild(); >+ RenderStyle* style = htmlObject->style(); >+ if (style->hasBackground()) >+ return style->backgroundColor(); >+ >+ RenderObject* bodyObject = htmlObject->firstChild(); >+ style = bodyObject->style(); >+ return style->backgroundColor(); >+ } >+ >+ return renderer()->style()->backgroundColor(); >+} >+ >+bool RenderLayerBacking::canBeSimpleContainerCompositingLayer() const >+{ >+ RenderObject* renderObject = renderer(); >+ if (renderObject->isReplaced() || // replaced objects are not containers >+ renderObject->hasMask()) // masks require special treatment >+ return false; >+ >+ RenderStyle* style = renderObject->style(); >+ >+ // Reject anything that has a border, a border-radius or outline, >+ // or any background (color or image). >+ // FIXME: we could optimize layers for simple backgrounds. >+ if (hasBorderOutlineOrShadow(style) || >+ style->hasBackground()) >+ return false; >+ >+ // If we have got this far and the renderer has no children, then we're ok. >+ if (!renderObject->firstChild()) >+ return true; >+ >+ if (renderObject->node()->isDocumentNode()) { >+ // Look to see if the root object has a non-simple backgound >+ RenderObject* rootObject = renderObject->document()->documentElement()->renderer(); >+ if (!rootObject) >+ return false; >+ >+ 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 (hasBorderOutlineOrShadow(style) || >+ !hasSimpleBackground(style)) >+ return false; >+ >+ // Now look at the body's renderer. >+ HTMLElement* body = renderObject->document()->body(); >+ RenderObject* bodyObject = (body && body->hasLocalName(HTMLNames::bodyTag)) ? body->renderer() : 0; >+ if (!bodyObject) >+ return false; >+ >+ style = bodyObject->style(); >+ >+ if (hasBorderOutlineOrShadow(style) || >+ !hasSimpleBackground(style)) >+ return false; >+ >+ // Ceck to see if all the body's children are compositing layers. >+ if (hasNonCompositingContent()) >+ return false; >+ >+ return true; >+ } >+ >+ // Check to see if all the renderer's children are compositing layers. >+ if (hasNonCompositingContent()) >+ return false; >+ >+ return true; >+} >+ >+bool RenderLayerBacking::hasNonCompositingContent() const >+{ >+ // Conservative test for having no rendered children. >+ >+ // Some HTML can cause whitespace text nodes to have renderers, like: >+ // <div> >+ // <img src=...> >+ // </div> >+ // so test for 0x0 RenderTexts here >+ for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) { >+ if (!child->hasLayer() && child->isBox() && (RenderBox::toRenderBox(child)->width() > 0 || RenderBox::toRenderBox(child)->height() > 0)) >+ return true; >+ } >+ >+ // FIXME: test for overflow controls. >+ if (m_owningLayer->isStackingContext()) { >+ // Use the m_hasCompositingDescendant bit to optimize? >+ Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList(); >+ if (negZOrderList && negZOrderList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ if (!curLayer->isComposited()) >+ return true; >+ } >+ } >+ >+ Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList(); >+ if (posZOrderList && posZOrderList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ if (!curLayer->isComposited()) >+ return true; >+ } >+ } >+ } >+ >+ Vector<RenderLayer*>* overflowList = m_owningLayer->overflowList(); >+ if (overflowList && overflowList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = overflowList->begin(); it != overflowList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ if (!curLayer->isComposited()) >+ return true; >+ } >+ } >+ >+ return false; >+} >+ >+// 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 RenderLayerBacking::isSimpleContainerCompositingLayer() >+{ >+ if (m_simpleCompositingLayerStatusDirty) { >+ m_isSimpleContainerCompositingLayer = canBeSimpleContainerCompositingLayer(); >+ m_simpleCompositingLayerStatusDirty = false; >+ } >+ >+ return m_isSimpleContainerCompositingLayer; >+} >+ >+void RenderLayerBacking::detectDrawingOptimizations() >+{ >+ bool drawsContent = true; >+ >+ if (isSimpleContainerCompositingLayer() || paintingGoesToWindow()) >+ drawsContent = false; >+ >+ m_graphicsLayer->setDrawsContent(drawsContent); >+} >+ >+void RenderLayerBacking::invalidateDrawingOptimizations() >+{ >+ m_simpleCompositingLayerStatusDirty = true; >+} >+ >+void RenderLayerBacking::forceCompositingLayer(bool force) >+{ >+ m_forceCompositingLayer = force; >+} >+ >+FloatPoint RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const >+{ >+ RenderStyle* style = renderer()->style(); >+ >+ FloatPoint origin; >+ origin.setX(style->transformOriginX().calcFloatValue(borderBox.width())); >+ origin.setY(style->transformOriginY().calcFloatValue(borderBox.height())); >+ >+ return origin; >+} >+ >+// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted. >+IntSize RenderLayerBacking::contentOffsetInCompostingLayer() >+{ >+ if (!m_compositingContentOffsetDirty) >+ return m_compositingContentOffset; >+ >+ IntRect relativeCompositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); >+ m_compositingContentOffset = IntSize(-relativeCompositingBounds.x(), -relativeCompositingBounds.y()); >+ m_compositingContentOffsetDirty = false; >+ >+ return m_compositingContentOffset; >+} >+ >+IntRect RenderLayerBacking::contentsBox(const GraphicsLayer*) >+{ >+ IntRect contentsRect = renderer()->contentBoxRect(); >+ IntSize contentOffset = contentOffsetInCompostingLayer(); >+ contentsRect.move(contentOffset); >+ return contentsRect; >+} >+ >+// Map the given point from coordinates in the GraphicsLayer to RenderLayer coordinates. >+FloatPoint RenderLayerBacking::graphicsLayerToContentsCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point) >+{ >+ return point + FloatSize(graphicsLayer->offsetFromRenderer()); >+} >+ >+// Map the given point from coordinates in the RenderLayer to GraphicsLayer coordinates. >+FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point) >+{ >+ return point - FloatSize(graphicsLayer->offsetFromRenderer()); >+} >+ >+bool RenderLayerBacking::paintingGoesToWindow() const >+{ >+ return m_owningLayer->isDocumentLayer(); >+} >+ >+void RenderLayerBacking::setContentsNeedDisplay() >+{ >+ if (m_graphicsLayer) >+ m_graphicsLayer->setNeedsDisplay(); >+ if (m_contentsLayer) >+ m_contentsLayer->setNeedsDisplay(); >+} >+ >+// r is in the coordinate space of the layer's render object >+void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) >+{ >+ if (m_graphicsLayer) { >+ FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer, FloatPoint(r.x(), r.y())); >+ FloatRect dirtyRect(dirtyOrigin, r.size()); >+ FloatRect bounds(FloatPoint(), m_graphicsLayer->size()); >+ if (bounds.intersects(dirtyRect)) >+ m_graphicsLayer->setNeedsDisplayInRect(dirtyRect); >+ } >+ >+ if (m_contentsLayer) { >+ // FIXME: do incremental repaint >+ m_contentsLayer->setNeedsDisplay(); >+ } >+} >+ >+static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) >+{ >+ if (paintDirtyRect == clipRect) >+ return; >+ p->save(); >+ p->clip(clipRect); >+} >+ >+static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) >+{ >+ if (paintDirtyRect == clipRect) >+ return; >+ p->restore(); >+} >+ >+// Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase? >+void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context, >+ const IntRect& paintDirtyRect, // in the coords of rootLayer >+ bool haveTransparency, PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase, >+ RenderObject* paintingRoot) >+{ >+ if (paintingGoesToWindow()) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ >+ if (m_owningLayer->isStackingContext() && (m_owningLayer->m_zOrderListsDirty || m_owningLayer->m_overflowListDirty)) >+ compositor()->updateCompositingLayers(m_owningLayer); >+ >+ // Calculate the clip rects we should use. >+ IntRect layerBounds, damageRect, clipRectToApply, outlineRect; >+ m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect); >+ >+ int x = layerBounds.x(); // layerBounds is computed relative to rootLayer >+ int y = layerBounds.y(); >+ int tx = x - renderer()->x(); >+ int ty = y - renderer()->y() + renderer()->borderTopExtra(); >+ >+ // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which >+ // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). >+ // Else, our renderer tree may or may not contain the painting root, so we pass that root along >+ // so it will be tested against as we decend through the renderers. >+ RenderObject *paintingRootForRenderer = 0; >+ if (paintingRoot && !renderer()->isDescendantOf(paintingRoot)) >+ paintingRootForRenderer = paintingRoot; >+ >+ if (paintingPhase & GraphicsLayerPaintBackgroundMask) { >+ // If this is the root then we need to send in a bigger bounding box >+ // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()). >+ IntRect paintBox = clipRectToApply; >+ >+ if (renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) { >+ int w = renderer()->width(); >+ int h = renderer()->height(); >+ >+ int rw; >+ int rh; >+ if (renderer()->view()->frameView()) { >+ rw = renderer()->view()->frameView()->contentsWidth(); >+ rh = renderer()->view()->frameView()->contentsHeight(); >+ } else { >+ rw = renderer()->view()->width(); >+ rh = renderer()->view()->height(); >+ } >+ >+ int bx = tx - renderer()->marginLeft(); >+ int by = ty - renderer()->marginTop(); >+ int bw = max(w + renderer()->marginLeft() + renderer()->marginRight() + renderer()->borderLeft() + renderer()->borderRight(), rw); >+ int bh = max(h + renderer()->marginTop() + renderer()->marginBottom() + renderer()->borderTop() + renderer()->borderBottom(), rh); >+ paintBox = IntRect(bx, by, bw, bh); >+ } >+ >+ // Paint our background first, before painting any child layers. >+ // Establish the clip used to paint our background. >+ setClip(context, paintDirtyRect, damageRect); >+ >+ RenderObject::PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0); >+ renderer()->paint(info, tx, ty); >+ >+ // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with >+ // z-index. We paint after we painted the background/border, so that the scrollbars will >+ // sit above the background/border. >+ m_owningLayer->paintOverflowControls(context, x, y, damageRect); >+ >+ // Restore the clip. >+ restoreClip(context, paintDirtyRect, damageRect); >+ } >+ >+ if (paintingPhase & GraphicsLayerPaintForegroundMask) { >+ // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint. >+ // FIXME: should these be painted as background? >+ Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList(); >+ if (negZOrderList) { >+ for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) >+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot); >+ } >+ >+ bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText; >+ bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText; >+ >+ // Set up the clip used when painting our children. >+ setClip(context, paintDirtyRect, clipRectToApply); >+ RenderObject::PaintInfo paintInfo(context, clipRectToApply, >+ selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, >+ forceBlackText, paintingRootForRenderer, 0); >+ renderer()->paint(paintInfo, tx, ty); >+ >+ if (!selectionOnly) { >+ paintInfo.phase = PaintPhaseFloat; >+ renderer()->paint(paintInfo, tx, ty); >+ >+ paintInfo.phase = PaintPhaseForeground; >+ renderer()->paint(paintInfo, tx, ty); >+ >+ paintInfo.phase = PaintPhaseChildOutlines; >+ renderer()->paint(paintInfo, tx, ty); >+ } >+ >+ // Now restore our clip. >+ restoreClip(context, paintDirtyRect, clipRectToApply); >+ >+ if (!outlineRect.isEmpty()) { >+ // Paint our own outline >+ RenderObject::PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); >+ setClip(context, paintDirtyRect, outlineRect); >+ renderer()->paint(paintInfo, tx, ty); >+ restoreClip(context, paintDirtyRect, outlineRect); >+ } >+ >+ // Paint any child layers that have overflow. >+ Vector<RenderLayer*>* overflowList = m_owningLayer->overflowList(); >+ if (overflowList) { >+ for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) >+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot); >+ } >+ >+ // Now walk the sorted list of children with positive z-indices. >+ Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList(); >+ if (posZOrderList) { >+ for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) >+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot); >+ } >+ >+ if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) { >+ setClip(context, paintDirtyRect, damageRect); >+ >+ // Paint the mask. >+ RenderObject::PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0); >+ renderer()->paint(paintInfo, tx, ty); >+ >+ // Restore the clip. >+ restoreClip(context, paintDirtyRect, damageRect); >+ } >+ } >+ >+ ASSERT(!m_owningLayer->m_usedTransparency); >+} >+ >+// Up-call from compositing layer drawing callback. >+void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase drawingPhase, const IntRect& clip) >+{ >+ // We have to use the same root as for hit testing, because both methods >+ // can compute and cache clipRects. >+ IntRect enclosingBBox = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); >+ >+ IntRect clipRect(clip); >+ >+ // Set up the coordinate space to be in the layer's rendering coordinates. >+ context.translate(-enclosingBBox.x(), -enclosingBBox.y()); >+ >+ // Offset the clip. >+ clipRect.move(enclosingBBox.x(), enclosingBBox.y()); >+ >+ // The dirtyRect is in the coords of the painting root. >+ IntRect dirtyRect = enclosingBBox; >+ dirtyRect.intersect(clipRect); >+ >+ paintIntoLayer(m_owningLayer, &context, dirtyRect, false, PaintRestrictionNone, drawingPhase, renderer()); >+} >+ >+bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes) >+{ >+ bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); >+ bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform); >+ >+ if (!hasOpacity && !hasTransform) >+ return false; >+ >+ GraphicsLayer::TransformValueList transformVector; >+ GraphicsLayer::FloatValueList opacityVector; >+ >+ for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) { >+ const RenderStyle* keyframeStyle = it->style(); >+ float key = it->key(); >+ >+ if (!keyframeStyle) >+ continue; >+ >+ // get timing function >+ const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0; >+ >+ if (hasTransform) >+ transformVector.insert(key, &(keyframeStyle->transform()), tf); >+ >+ if (hasOpacity) >+ opacityVector.insert(key, keyframeStyle->opacity(), tf); >+ } >+ >+ bool didAnimateTransform = !hasTransform; >+ bool didAnimateOpacity = !hasOpacity; >+ >+ if (hasTransform && m_graphicsLayer->animateTransform(transformVector, renderer()->borderBoxRect().size(), anim, beginTime, false)) >+ didAnimateTransform = true; >+ >+ if (hasOpacity && m_graphicsLayer->animateFloat(AnimatedPropertyOpacity, opacityVector, anim, beginTime)) >+ didAnimateOpacity = true; >+ >+ return didAnimateTransform && didAnimateOpacity; >+} >+ >+bool RenderLayerBacking::startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle) >+{ >+ bool didAnimate = false; >+ >+ if (property == cAnimateAll || property == (int)CSSPropertyOpacity) { >+ const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity); >+ if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) { >+ // If beginTime is not 0, we are restarting this transition, so first set the from value >+ // in case it was smashed by a previous animation. >+ if (beginTime > 0) >+ m_graphicsLayer->setOpacity(compositingOpacity(fromStyle->opacity()), 0, 0); >+ >+ if (m_graphicsLayer->setOpacity(compositingOpacity(toStyle->opacity()), opacityAnim, beginTime)) >+ didAnimate = true; >+ } >+ } >+ if (property == cAnimateAll || property == (int)CSSPropertyWebkitTransform) { >+ // We get a TransformOperation, which is a linked list of primitive operations and their arguments. >+ // Arguments can be floats or Length values, which need to be converted to numbers using >+ // val.calcFloatValue(renderer()->width()) (or height()). >+ const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform); >+ if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) { >+ GraphicsLayer::TransformValueList transformVector; >+ transformVector.insert(0, &fromStyle->transform(), 0); >+ transformVector.insert(1, &toStyle->transform(), 0); >+ if (m_graphicsLayer->animateTransform(transformVector, renderer()->borderBoxRect().size(), transformAnim, beginTime, true)) >+ didAnimate = true; >+ } >+ } >+ >+ return didAnimate; >+} >+ >+void RenderLayerBacking::notifyTransitionStarted(const GraphicsLayer*, AnimatedPropertyID property, double time) >+{ >+ int cssProperty = CSSPropertyInvalid; >+ switch (property) { >+ case AnimatedPropertyInvalid: >+ break; >+ case AnimatedPropertyWebkitTransform: >+ cssProperty = CSSPropertyWebkitTransform; >+ break; >+ case AnimatedPropertyOpacity: >+ cssProperty = CSSPropertyOpacity; >+ break; >+ case AnimatedPropertyBackgroundColor: >+ cssProperty = CSSPropertyBackgroundColor; >+ break; >+ } >+ >+ renderer()->notifyTransitionStarted(cssProperty, time); >+} >+ >+void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time) >+{ >+ renderer()->notifyAnimationStarted(time); >+} >+ >+void RenderLayerBacking::animationFinished(const String& name, int index, bool reset) >+{ >+ m_graphicsLayer->removeFinishedAnimations(name, index, reset); >+} >+ >+void RenderLayerBacking::transitionFinished(int property) >+{ >+ m_graphicsLayer->removeFinishedTransitions(property); >+} >+ >+void RenderLayerBacking::suspendAnimations() >+{ >+ m_graphicsLayer->suspendAnimations(); >+} >+ >+void RenderLayerBacking::resumeAnimations() >+{ >+ m_graphicsLayer->resumeAnimations(); >+} >+ >+} // namespace WebCore >+ >+#endif // USE(ACCELERATED_COMPOSITING) >diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h >new file mode 100644 >index 0000000..9d59d40 >--- /dev/null >+++ b/WebCore/rendering/RenderLayerBacking.h >@@ -0,0 +1,170 @@ >+/* >+ * Copyright (C) 2009 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef RenderLayerBacking_h >+#define RenderLayerBacking_h >+ >+#if USE(ACCELERATED_COMPOSITING) >+ >+#include "FloatPoint.h" >+#include "FloatPoint3D.h" >+#include "GraphicsLayer.h"; >+#include "GraphicsLayerClient.h"; >+#include "RenderLayer.h" >+#include "TransformationMatrix.h" >+ >+namespace WebCore { >+ >+class RenderLayerCompositor; >+ >+// RenderLayerBacking controls the compositing behavior for a single RenderLayer. >+// It holds the various GraphicsLayers, and makes decisions about intra-layer rendering >+// optimizations. >+// >+// There is one RenderLayerBacking for each RenderLayer that is composited. >+ >+class RenderLayerBacking : public GraphicsLayerClient { >+public: >+ RenderLayerBacking(RenderLayer*); >+ ~RenderLayerBacking(); >+ >+ RenderLayer* owningLayer() const { return m_owningLayer; } >+ >+ void updateAfterLayout(); >+ >+ // Returns true if layer configuration changed. >+ bool updateGraphicsLayers(bool needsContentsLayer, bool needsUpperClippingLayer, bool needsLowerClippingLayer, bool needsRepaint); >+ void updateGraphicsLayerGeometry(); >+ void updateInternalHierarchy(); >+ >+ GraphicsLayer* graphicsLayer() const { return m_graphicsLayer; } >+ >+ // Layer to clip children >+ bool hasClippingLayer() const { return m_clippingLayer != 0; } >+ GraphicsLayer* clippingLayer() const { return m_clippingLayer; } >+ >+ // Layer to get clipped by ancestor >+ bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; } >+ GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer; } >+ >+ bool hasContentsLayer() const { return m_contentsLayer != 0; } >+ GraphicsLayer* contentsLayer() const { return m_contentsLayer; } >+ >+ GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer : m_graphicsLayer; } >+ GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer : m_graphicsLayer; } >+ >+ // RenderLayers with backing normally short-circuit paintLayer() because >+ // their content is rendered via callbacks from GraphicsLayer. However, the document >+ // layer is special, because it has a GraphicsLayer to act as a container for the GraphicsLayers >+ // for descendants, but its contents usually render into the window (in which case this returns true). >+ // This returns false for other layers, and when the document layer actually needs to paint into its backing store >+ // for some reason. >+ bool paintingGoesToWindow() const; >+ >+ void setContentsNeedDisplay(); >+ // r is in the coordinate space of the layer's render object >+ void setContentsNeedDisplayInRect(const IntRect& r); >+ >+ // Interface to start, finish, suspend and resume animations and transitions >+ bool startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes); >+ bool startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle); >+ void animationFinished(const String& name, int index, bool reset); >+ void transitionFinished(int property); >+ >+ void suspendAnimations(); >+ void resumeAnimations(); >+ >+ FloatPoint graphicsLayerToContentsCoordinates(const GraphicsLayer*, const FloatPoint&); >+ FloatPoint contentsToGraphicsLayerCoordinates(const GraphicsLayer*, const FloatPoint&); >+ >+ void forceCompositingLayer(bool force = true); >+ bool forcedCompositingLayer() const { return m_forceCompositingLayer; } >+ >+ void detectDrawingOptimizations(); >+ void invalidateDrawingOptimizations(); >+ >+ // GraphicsLayerClient interface >+ virtual void notifyTransitionStarted(const GraphicsLayer*, AnimatedPropertyID, double startTime); >+ virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime); >+ >+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip); >+ >+ virtual IntRect contentsBox(const GraphicsLayer*); >+ >+private: >+ void createGraphicsLayer(); >+ void destroyGraphicsLayer(); >+ >+ RenderBox* renderer() const { return m_owningLayer->renderer(); } >+ RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); } >+ >+ bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip); >+ bool updateContentsLayer(bool needsContentsLayer); >+ >+ IntSize contentOffsetInCompostingLayer(); >+ // Result is transform origin in pixels. >+ FloatPoint computeTransformOrigin(const IntRect& borderBox) const; >+ >+ void updateLayerOpacity(); >+ void updateLayerTransform(); >+ >+ // Return the opacity value that this layer should use for compositing. >+ float compositingOpacity(float rendererOpacity) const; >+ >+ // Returns true if this RenderLayer only has content that can be rendered directly >+ // by the compositing layer, without drawing (e.g. solid background color). >+ bool isSimpleContainerCompositingLayer(); >+ >+ bool rendererHasBackground() const; >+ const Color& rendererBackgroundColor() const; >+ >+ bool canBeSimpleContainerCompositingLayer() const; >+ bool hasNonCompositingContent() const; >+ >+ void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, >+ bool haveTransparency, PaintRestriction paintRestriction, GraphicsLayerPaintingPhase, RenderObject* paintingRoot); >+ >+private: >+ RenderLayer* m_owningLayer; >+ >+ GraphicsLayer* m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context >+ GraphicsLayer* m_graphicsLayer; >+ GraphicsLayer* m_contentsLayer; // only used in cases where we need to draw the foreground separately >+ GraphicsLayer* m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children >+ >+ IntSize m_compositingContentOffset; >+ >+ bool m_forceCompositingLayer : 1; // set if we need a compositing layer because of some external requirement >+ bool m_isSimpleContainerCompositingLayer : 1; // is this compositing layer able to be simplified >+ bool m_simpleCompositingLayerStatusDirty : 1; // set if the test for simple layers needs to be redone >+ >+ bool m_compositingContentOffsetDirty: 1; >+}; >+ >+} // namespace WebCore >+ >+#endif // USE(ACCELERATED_COMPOSITING) >+ >+#endif // RenderLayerBacking_h >diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp >new file mode 100644 >index 0000000..413d6ea >--- /dev/null >+++ b/WebCore/rendering/RenderLayerCompositor.cpp >@@ -0,0 +1,749 @@ >+/* >+ * Copyright (C) 2009 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+ >+#if USE(ACCELERATED_COMPOSITING) >+#include "RenderLayerCompositor.h" >+ >+#include "AnimationController.h" >+#include "ChromeClient.h" >+#include "FrameView.h" >+#include "GraphicsLayer.h" >+#include "HitTestRequest.h" >+#include "HitTestResult.h" >+#include "Page.h" >+#include "RenderLayerBacking.h" >+#include "RenderView.h" >+ >+#if PROFILE_LAYER_REBUILD >+#include <wtf/CurrentTime.h> >+#endif >+ >+#ifndef NDEBUG >+#include "CString.h" >+#include "RenderTreeAsText.h" >+#endif >+ >+namespace WebCore { >+ >+struct CompositingState { >+ CompositingState(RenderLayer* compAncestor) >+ : m_subtreeIsCompositing(false) >+ , m_compositingAncestor(compAncestor) >+#ifndef NDEBUG >+ , m_depth(0) >+#endif >+ { >+ } >+ >+ bool m_subtreeIsCompositing; >+ RenderLayer* m_compositingAncestor; >+#ifndef NDEBUG >+ int m_depth; >+#endif >+}; >+ >+static TransformationMatrix flipTransform() >+{ >+ TransformationMatrix flipper; >+ flipper.flipY(); >+ return flipper; >+} >+ >+RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) >+ : m_renderView(renderView) >+ , m_rootPlatformLayer(0) >+ , m_compositing(false) >+ , m_rootLayerAttached(false) >+ , m_compositingLayersNeedUpdate(false) >+#if PROFILE_LAYER_REBUILD >+ , m_rootLayerUpdateCount(0) >+#endif // PROFILE_LAYER_REBUILD >+{ >+} >+ >+RenderLayerCompositor::~RenderLayerCompositor() >+{ >+ ASSERT(!m_rootLayerAttached); >+ delete m_rootPlatformLayer; >+} >+ >+void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) >+{ >+ if (enable != m_compositing) { >+ m_compositing = enable; >+ >+ // We never go out of compositing mode for a given page, >+ // but if all the layers disappear, we'll just be left with >+ // the empty root layer, which has minimal overhead. >+ if (m_compositing) >+ ensureRootPlatformLayer(); >+ } >+} >+ >+void RenderLayerCompositor::setCompositingLayersNeedUpdate(bool needUpdate) >+{ >+ if (inCompositingMode()) >+ m_compositingLayersNeedUpdate = needUpdate; >+} >+ >+void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot) >+{ >+ if (!m_compositingLayersNeedUpdate) >+ return; >+ >+ m_compositingLayersNeedUpdate = false; >+ >+ ASSERT(inCompositingMode()); >+ >+ if (!updateRoot) >+ updateRoot = rootRenderLayer(); >+ >+#if PROFILE_LAYER_REBUILD >+ ++m_rootLayerUpdateCount; >+ >+ double startTime = WTF::currentTime(); >+#endif >+ >+ // Go through the layers in presentation order, so that we can compute which >+ // RLs need compositing layers. >+ // FIXME: we could maybe do this in one pass, but the parenting logic would be more >+ // complex. >+ { >+ CompositingState compState(updateRoot); >+ computeCompositingRequirements(updateRoot, compState); >+ } >+ >+ // Now create and parent the compositing layers. >+ { >+ CompositingState compState(updateRoot); >+ rebuildCompositingLayerTree(updateRoot, compState); >+ } >+ >+#if PROFILE_LAYER_REBUILD >+ double endTime = WTF::currentTime(); >+ if (!updateRoot) >+ fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n" >+ m_rootLayerUpdateCount, 1000.0 * (endTime - startTime)); >+#endif >+ ASSERT(!m_compositingLayersNeedUpdate); >+} >+ >+bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, RenderStyle::Diff diff) >+{ >+ bool needsLayer = needsToBeComposited(layer); >+ bool layerChanged = false; >+ if (needsLayer) { >+ enableCompositingMode(); >+ if (!layer->backing()) { >+ layer->ensureBacking(); >+ layerChanged = true; >+ } >+ } else { >+ if (layer->backing()) { >+ layer->clearBacking(); >+ layerChanged = true; >+ } >+ } >+ >+ if (layerChanged) { >+ // invalidate the parent in this region >+ RenderLayer* compLayer = enclosingCompositingLayer(layer, false); >+ if (compLayer) { >+ // We can't reliably compute a dirty rect, because style may have changed already, >+ // so just dirty the whole parent layer >+ compLayer->setNeedsRepaint(); >+ // The contents of this layer may be moving between the window >+ // and a GraphicsLayer, so we need to make sure the window system >+ // synchronizes those changes on the screen. >+ m_renderView->frameView()->setNeedsSynchronizedGraphicsFlush(); >+ } >+ >+ layer->renderer()->compositingStateChanged(); >+ } >+ >+ if (!needsLayer) >+ return layerChanged; >+ >+ if (layer->backing()->updateGraphicsLayers(needsContentsCompositingLayer(layer), >+ clippedByAncestor(layer), >+ clipsCompositingDescendants(layer), >+ diff >= RenderStyle::Repaint)) >+ layerChanged = true; >+ >+ return layerChanged; >+} >+ >+// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant >+// RenderLayers that are rendered by the composited RenderLayer. >+IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox) >+{ >+ IntRect boundingBoxRect, unionBounds; >+ boundingBoxRect = unionBounds = layer->boundingBox(layer); >+ >+ ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0)); >+ >+ Vector<RenderLayer*>* negZOrderList = layer->negZOrderList(); >+ if (negZOrderList) { >+ for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ if (!curLayer->isComposited()) { >+ IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); >+ unionBounds.unite(childUnionBounds); >+ } >+ } >+ } >+ >+ Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); >+ if (posZOrderList) { >+ for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ if (!curLayer->isComposited()) { >+ IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); >+ unionBounds.unite(childUnionBounds); >+ } >+ } >+ } >+ >+ Vector<RenderLayer*>* overflowList = layer->overflowList(); >+ if (overflowList) { >+ for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ if (!curLayer->isComposited()) { >+ IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer); >+ unionBounds.unite(curAbsBounds); >+ } >+ } >+ } >+ >+ if (!layer->isComposited() && layer->transform()) { >+ TransformationMatrix* affineTrans = layer->transform(); >+ boundingBoxRect = affineTrans->mapRect(boundingBoxRect); >+ unionBounds = affineTrans->mapRect(unionBounds); >+ } >+ >+ int ancestorRelX = 0, ancestorRelY = 0; >+ layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY); >+ unionBounds.move(ancestorRelX, ancestorRelY); >+ >+ if (layerBoundingBox) { >+ boundingBoxRect.move(ancestorRelX, ancestorRelY); >+ *layerBoundingBox = boundingBoxRect; >+ } >+ >+ return unionBounds; >+} >+ >+void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/) >+{ >+ setCompositingLayersNeedUpdate(); >+} >+ >+void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child) >+{ >+ if (child->isComposited()) >+ setCompositingParent(child, 0); >+ >+ RenderLayer* compLayer = enclosingCompositingLayer(parent, false); >+ if (compLayer) { >+ IntRect ancestorRect = calculateCompositedBounds(child, compLayer); >+ compLayer->setNeedsRepaintInRect(ancestorRect); >+ // The contents of this layer may be moving from a GraphicsLayer to the window, >+ // so we need to make sure the window system synchronizes those changes on the screen. >+ m_renderView->frameView()->setNeedsSynchronizedGraphicsFlush(); >+ } >+ >+ setCompositingLayersNeedUpdate(); >+} >+ >+RenderLayer* RenderLayerCompositor::enclosingCompositingLayer(RenderLayer* layer, bool includeSelf) const >+{ >+ if (includeSelf && layer->isComposited()) >+ return layer; >+ >+ bool childOverflowOnly = layer->isOverflowOnly(); >+ for (RenderLayer* curr = layer->parent(); curr; curr = curr->parent()) { >+ // Compositing layers are parented according to stacking order and overflow list, >+ // so we have to check whether the parent is a stacking context, or whether >+ // the child is overflow-only. >+ if (curr->isComposited() && (childOverflowOnly || curr->isStackingContext())) >+ return curr; >+ >+ childOverflowOnly = curr->isOverflowOnly(); >+ } >+ >+ return 0; >+} >+ >+RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const >+{ >+ for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) { >+ if (curr->isStackingContext()) >+ return 0; >+ >+ if (curr->renderer()->hasOverflowClip()) >+ return curr; >+ } >+ return 0; >+} >+ >+// Recurse through the layers in z-index and overflow order (which is equivalent to painting order) >+// For the z-order children of a compositing layer: >+// If a child layers has a compositing layer, then all subsequent layers must >+// be compositing in order to render above that layer. >+// >+// If a child in the negative z-order list is compositing, then the layer itself >+// must be compositing so that its contents render over that child. >+// This implies that its positive z-index children must also be compositing. >+// >+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, struct CompositingState& ioCompState) >+{ >+ // Make sure this layer's z-order and overflow lists are up to date >+ layer->updateThisLayer(); >+ >+ // Clear the flag >+ layer->setHasCompositingDescendant(false); >+ >+ setForcedCompositingLayer(layer, ioCompState.m_subtreeIsCompositing); >+ >+ const bool isCompositingLayer = needsToBeComposited(layer); >+ ioCompState.m_subtreeIsCompositing = isCompositingLayer; >+ >+ CompositingState childState = ioCompState; >+ if (isCompositingLayer) >+ childState.m_compositingAncestor = layer; >+ >+ // The children of this stacking context don't need to composite, unless there is >+ // a compositing layer among them, so start by assuming false. >+ childState.m_subtreeIsCompositing = false; >+ >+#ifndef NDEBUG >+ ++childState.m_depth; >+#endif >+ >+ if (layer->isStackingContext()) { >+ ASSERT(!layer->m_zOrderListsDirty); >+ Vector<RenderLayer*>* negZOrderList = layer->negZOrderList(); >+ if (negZOrderList && negZOrderList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ computeCompositingRequirements(curLayer, childState); >+ >+ // if we have to make a layer for this child, make one now so we can have a contents layer >+ // (since we need to ensure that the -ve z-order child renders underneath our contents) >+ if (childState.m_subtreeIsCompositing) { >+ // make |this| compositing >+ setForcedCompositingLayer(layer, true); >+ childState.m_compositingAncestor = layer; >+ } >+ } >+ } >+ } >+ >+ ASSERT(!layer->m_overflowListDirty); >+ Vector<RenderLayer*>* overflowList = layer->overflowList(); >+ if (overflowList && overflowList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = overflowList->begin(); it != overflowList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ computeCompositingRequirements(curLayer, childState); >+ } >+ } >+ >+ if (layer->isStackingContext()) { >+ Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); >+ if (posZOrderList && posZOrderList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ computeCompositingRequirements(curLayer, childState); >+ } >+ } >+ } >+ >+ // If we have a software transform, and we have layers under us, we need to also >+ // be composited. Also, if we have opacity < 1, then we need to be a layer so that >+ // the child layers are opaque, then rendered with opacity on this layer. >+ if (childState.m_subtreeIsCompositing && >+ (layer->renderer()->style()->hasTransform() || layer->renderer()->style()->opacity() < 1)) >+ setForcedCompositingLayer(layer, true); >+ >+ // Subsequent layers in the parent stacking context also need to composite. >+ if (childState.m_subtreeIsCompositing) >+ ioCompState.m_subtreeIsCompositing = true; >+ >+ // Set the flag to say that this SC has compositing children. >+ // this can affect the answer to needsToBeComposited() when clipping, >+ // but that's ok here. >+ layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing); >+} >+ >+void RenderLayerCompositor::setForcedCompositingLayer(RenderLayer* layer, bool force) >+{ >+ if (force) { >+ layer->ensureBacking(); >+ layer->backing()->forceCompositingLayer(); >+ } else { >+ if (layer->backing()) >+ layer->backing()->forceCompositingLayer(false); >+ } >+} >+ >+void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) >+{ >+ ASSERT(childLayer->isComposited()); >+ ASSERT(!parentLayer || parentLayer->isComposited()); >+ >+ if (parentLayer) { >+ GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers(); >+ GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers(); >+ >+ hostingLayer->addChild(hostedLayer); >+ } else >+ childLayer->backing()->childForSuperlayers()->removeFromParent(); >+ >+ // FIXME: setCompositingParent() is only called at present by rebuildCompositingLayerTree(), >+ // which calls updateGraphicsLayerGeometry via updateLayerCompositingState(), so this should >+ // be optimized. >+ if (parentLayer) >+ childLayer->backing()->updateGraphicsLayerGeometry(); >+} >+ >+void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer) >+{ >+ ASSERT(layer->isComposited()); >+ >+ GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers(); >+ hostingLayer->removeAllChildren(); >+} >+ >+void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer) >+{ >+ ASSERT(layer->isComposited()); >+ >+ GraphicsLayer* layerAnchor = layer->backing()->childForSuperlayers(); >+ >+ if (layerAnchor->parent() != m_rootPlatformLayer) { >+ layerAnchor->removeFromParent(); >+ if (m_rootPlatformLayer) >+ m_rootPlatformLayer->addChild(layerAnchor); >+ } >+} >+ >+void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& ioCompState) >+{ >+ updateLayerCompositingState(layer, RenderStyle::Equal); >+ >+ // host the document layer in the RenderView's root layer >+ if (layer->isDocumentLayer()) >+ parentInRootLayer(layer); >+ >+ CompositingState childState = ioCompState; >+ if (layer->isComposited()) >+ childState.m_compositingAncestor = layer; >+ >+#ifndef NDEBUG >+ ++childState.m_depth; >+#endif >+ >+ RenderLayerBacking* layerBacking = layer->backing(); >+ >+ // FIXME: make this more incremental >+ if (layer->isComposited()) { >+ layerBacking->parentForSublayers()->removeAllChildren(); >+ layerBacking->updateInternalHierarchy(); >+ } >+ >+ // The children of this stacking context don't need to composite, unless there is >+ // a compositing layer among them, so start by assuming false. >+ childState.m_subtreeIsCompositing = false; >+ >+ if (layer->isStackingContext()) { >+ ASSERT(!layer->m_zOrderListsDirty); >+ >+ Vector<RenderLayer*>* negZOrderList = layer->negZOrderList(); >+ if (negZOrderList && negZOrderList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ rebuildCompositingLayerTree(curLayer, childState); >+ if (curLayer->isComposited()) >+ setCompositingParent(curLayer, childState.m_compositingAncestor); >+ } >+ } >+ >+ if (layerBacking && layerBacking->contentsLayer()) { >+ // we only have a contents layer if we have an m_layer >+ layerBacking->contentsLayer()->removeFromParent(); >+ >+ GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer(); >+ hostingLayer->addChild(layerBacking->contentsLayer()); >+ } >+ } >+ >+ ASSERT(!layer->m_overflowListDirty); >+ Vector<RenderLayer*>* overflowList = layer->overflowList(); >+ if (overflowList && overflowList->size() > 0) { >+ for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ rebuildCompositingLayerTree(curLayer, childState); >+ if (curLayer->isComposited()) >+ setCompositingParent(curLayer, childState.m_compositingAncestor); >+ } >+ } >+ >+ if (layer->isStackingContext()) { >+ Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); >+ if (posZOrderList && posZOrderList->size() > 0) { >+ for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ rebuildCompositingLayerTree(curLayer, childState); >+ if (curLayer->isComposited()) >+ setCompositingParent(curLayer, childState.m_compositingAncestor); >+ } >+ } >+ } >+} >+ >+// repaint the given rect in this layer, and optionally the rect in all child layers >+void RenderLayerCompositor::repaintCompositingLayerRect(RenderLayer* layer, const IntRect& inRect, bool includeDescendants) >+{ >+ if (layer->isComposited()) >+ layer->backing()->setContentsNeedDisplayInRect(inRect); >+ >+ if (layer->hasCompositingDescendant() && includeDescendants) { >+ ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0)); >+ >+ Vector<RenderLayer*>* negZOrderList = layer->negZOrderList(); >+ if (negZOrderList) { >+ for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ int x = 0, y = 0; >+ curLayer->convertToLayerCoords(layer, x, y); >+ IntRect childRect(inRect); >+ childRect.move(-x, -y); >+ repaintCompositingLayerRect(curLayer, childRect, true); >+ } >+ } >+ >+ Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); >+ if (posZOrderList) { >+ for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ int x = 0, y = 0; >+ curLayer->convertToLayerCoords(layer, x, y); >+ IntRect childRect(inRect); >+ childRect.move(-x, -y); >+ repaintCompositingLayerRect(curLayer, childRect, true); >+ } >+ } >+ >+ Vector<RenderLayer*>* overflowList = layer->overflowList(); >+ if (overflowList) { >+ for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) { >+ RenderLayer* curLayer = (*it); >+ int x = 0, y = 0; >+ curLayer->convertToLayerCoords(layer, x, y); >+ IntRect childRect(inRect); >+ childRect.move(-x, -y); >+ repaintCompositingLayerRect(curLayer, childRect, true); >+ } >+ } >+ } >+} >+ >+RenderLayer* RenderLayerCompositor::rootRenderLayer() const >+{ >+ return m_renderView->layer(); >+} >+ >+GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const >+{ >+ return m_rootPlatformLayer; >+} >+ >+void RenderLayerCompositor::willBeDetached() >+{ >+ if (!m_rootPlatformLayer ||! m_rootLayerAttached) >+ return; >+ >+ Frame* frame = m_renderView->frameView()->frame(); >+ Page* page = frame ? frame->page() : 0; >+ if (!page) >+ return; >+ >+ page->chrome()->client()->attachRootGraphicsLayer(frame, 0); >+ m_rootLayerAttached = false; >+} >+ >+void RenderLayerCompositor::wasAttached() >+{ >+ if (!m_rootPlatformLayer) >+ return; >+ >+ Frame* frame = m_renderView->frameView()->frame(); >+ Page* page = frame ? frame->page() : 0; >+ if (!page) >+ return; >+ >+ page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer); >+ m_rootLayerAttached = true; >+} >+ >+void RenderLayerCompositor::updateRootLayerPosition() >+{ >+ if (m_rootPlatformLayer) >+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); >+} >+ >+bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const >+{ >+ return requiresCompositingLayer(layer) || (layer->backing() && layer->backing()->forcedCompositingLayer()); >+} >+ >+static bool requiresCompositingLayerForTransform(const RenderStyle*) >+{ >+ return false; >+} >+ >+#define VERBOSE_COMPOSITINGLAYER 0 >+ >+// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. >+// Use needsToBeComposited() to determine if a RL actually needs a compositing layer. >+// static >+bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const >+{ >+ // TODO: cache the result of these tests? >+ const RenderStyle* renderStyle = layer->renderer()->style(); >+ >+#if VERBOSE_COMPOSITINGLAYER >+ bool gotReason = false; >+ >+ if (!gotReason && inCompositingMode() && layer->isDocumentLayer()) { >+ fprintf(stderr, "RenderLayer %p requires compositing layer because: it's the document root\n", layer); >+ gotReason = true; >+ } >+ >+ if (!gotReason && requiresCompositingLayerForTransform(renderStyle)) { >+ fprintf(stderr, "RenderLayer %p requires compositing layer because: it has 3d transform, perspective, backface, or animating transform\n", layer); >+ gotReason = true; >+ } >+ >+ if (!gotReason && clipsCompositingDescendants(layer)) { >+ fprintf(stderr, "RenderLayer %p requires compositing layer because: it has overflow clip\n", layer); >+ gotReason = true; >+ } >+ >+ if (!gotReason && requiresCompositingForAnimation(layer)) { >+ fprintf(stderr, "RenderLayer %p requires compositing layer because: it has a running transition for opacity or transform\n", layer); >+ gotReason = true; >+ } >+ >+ if (!gotReason) >+ fprintf(stderr, "RenderLayer %p does not require compositing layer\n", layer); >+#endif >+ >+ // the root layer always has a compositing layer (for now). >+ return (inCompositingMode() && layer->isDocumentLayer()) || >+ requiresCompositingLayerForTransform(renderStyle) || >+ clipsCompositingDescendants(layer) || >+ requiresCompositingForAnimation(layer); >+} >+ >+// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, >+// up to the enclosing compositing ancestor. This is required because compositing layers are parented >+// according to the z-order hierarchy, yet clipping goes down the renderer hierarchy. >+// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy, >+// but a sibling in the z-order hierarchy. >+bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const >+{ >+ if (!layer->isComposited() || !layer->parent()) >+ return false; >+ >+ RenderLayer* compositingAncestor = enclosingCompositingLayer(layer, false); >+ >+ // We need ancestor clipping if something clips between this layer and its compositing, stacking context ancestor >+ for (RenderLayer* curLayer = layer->parent(); curLayer && curLayer != compositingAncestor; curLayer = curLayer->parent()) { >+ // FIXME: need to look at hasClip() too eventually >+ if (curLayer->renderer()->hasOverflowClip()) >+ return true; >+ >+ // Clip is reset for an absolutely positioned element. >+ // FIXME: many cases are broken. We need more of the logic in calculateClipRects() here >+ if (curLayer->renderer()->style()->position() == AbsolutePosition) >+ break; >+ } >+ >+ return false; >+} >+ >+// Return true if the given layer is a stacking context and has compositing child >+// layers that it needs to clip. In this case we insert a clipping GraphicsLayer >+// into the hierarchy between this layer and its children in the z-order hierarchy. >+bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const >+{ >+ // FIXME: need to look at hasClip() too eventually >+ return layer->hasCompositingDescendant() && >+ layer->isStackingContext() && >+ layer->renderer()->hasOverflowClip(); >+} >+ >+bool RenderLayerCompositor::requiresCompositingForAnimation(const RenderLayer* layer) const >+{ >+ AnimationController* animController = layer->renderer()->animation(); >+ if (animController) >+ return animController->isAnimatingPropertyOnRenderer(layer->renderer(), CSSPropertyOpacity) || >+ animController->isAnimatingPropertyOnRenderer(layer->renderer(), CSSPropertyWebkitTransform); >+ return false; >+} >+ >+// If an element has negative z-index children, those children render in front of the >+// layer background, so we need an extra 'contents' layer for the foreground of the layer >+// object. >+bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const >+{ >+ return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0); >+} >+ >+void RenderLayerCompositor::ensureRootPlatformLayer() >+{ >+ if (m_rootPlatformLayer) >+ return; >+ >+ m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0); >+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); >+ m_rootPlatformLayer->setPosition(FloatPoint(0, 0)); >+ >+ if (GraphicsLayer::graphicsContextsFlipped()) >+ m_rootPlatformLayer->setChildrenTransform(flipTransform()); >+ >+ // Need to clip to prevent transformed content showing outside this frame >+ m_rootPlatformLayer->setMasksToBounds(true); >+ >+ wasAttached(); >+} >+ >+} // namespace WebCore >+ >+#endif // USE(ACCELERATED_COMPOSITING) >+ >diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h >new file mode 100644 >index 0000000..1efc257 >--- /dev/null >+++ b/WebCore/rendering/RenderLayerCompositor.h >@@ -0,0 +1,134 @@ >+/* >+ * Copyright (C) 2009 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef RenderLayerCompositor_h >+#define RenderLayerCompositor_h >+ >+#include "RenderLayer.h" >+ >+namespace WebCore { >+ >+#define PROFILE_LAYER_REBUILD 0 >+ >+class GraphicsLayer; >+ >+// RenderLayerCompositor manages the hierarchy of >+// composited RenderLayers. It determines which RenderLayers >+// become compositing, and creates and maintains a hierarchy of >+// GraphicsLayers based on the RenderLayer painting order. >+// >+// There is one RenderLayerCompositor per RenderView. >+ >+class RenderLayerCompositor { >+public: >+ >+ RenderLayerCompositor(RenderView*); >+ ~RenderLayerCompositor(); >+ >+ // Return true if this RenderView is in "compositing mode" (i.e. has one or more >+ // composited RenderLayers) >+ bool inCompositingMode() const { return m_compositing; } >+ // This will make a compositing layer at the root automatically, and hook up to >+ // the native view/window system. >+ void enableCompositingMode(bool enable = true); >+ >+ void setCompositingLayersNeedUpdate(bool needUpdate = true); >+ bool compositingLayersNeedUpdate() const { return m_compositingLayersNeedUpdate; } >+ >+ // Rebuild the tree of compositing layers >+ void updateCompositingLayers(RenderLayer* updateRoot = 0); >+ >+ // Update the compositing state of the given layer. Returns true if that state changed >+ bool updateLayerCompositingState(RenderLayer*, RenderStyle::Diff); >+ >+ // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer. >+ // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only. >+ IntRect calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox = 0); >+ >+ // Notify us that a layer has been added or removed >+ void layerWasAdded(RenderLayer* parent, RenderLayer* child); >+ void layerWillBeRemoved(RenderLayer* parent, RenderLayer* child); >+ >+ // Gets the nearest enclosing render layer that is composited (optionally including self) >+ RenderLayer* enclosingCompositingLayer(RenderLayer* layer, bool includeSelf = true) const; >+ >+ // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context >+ RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const; >+ >+ void repaintCompositingLayerRect(RenderLayer*, const IntRect&, bool includeDescendants); >+ >+ RenderLayer* rootRenderLayer() const; >+ GraphicsLayer* rootPlatformLayer() const; >+ >+ void willBeDetached(); >+ void wasAttached(); >+ void updateRootLayerPosition(); >+ >+private: >+ // Whether the given RL needs a compositing layer. >+ bool needsToBeComposited(const RenderLayer*) const; >+ // Whether the layer has an intrinsic need for compositing layer. >+ bool requiresCompositingLayer(const RenderLayer*) const; >+ >+ // Whether we need a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow). >+ bool clippedByAncestor(RenderLayer*) const; >+ // Whether we need a graphics layer to clip z-order children of the given layer. >+ bool clipsCompositingDescendants(const RenderLayer*) const; >+ >+ // Whether a running transition or animation enforces the need for a compositing layer. >+ bool requiresCompositingForAnimation(const RenderLayer*) const; >+ // Whether the given layer needs an extra 'contents' layer. >+ bool needsContentsCompositingLayer(const RenderLayer*) const; >+ >+ // Set a bit on this layer to force it to be composisted, because it has to render on top of >+ // other compositing layers. >+ void setForcedCompositingLayer(RenderLayer*, bool force); >+ >+ void computeCompositingRequirements(RenderLayer*, struct CompositingState&); >+ void rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState&); >+ >+ // Hook compositing layers together >+ void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer); >+ void removeCompositedChildren(RenderLayer*); >+ >+ void parentInRootLayer(RenderLayer*); >+ >+ void ensureRootPlatformLayer(); >+ >+private: >+ RenderView* m_renderView; >+ GraphicsLayer* m_rootPlatformLayer; >+ bool m_compositing; >+ bool m_rootLayerAttached; >+ bool m_compositingLayersNeedUpdate; >+#if PROFILE_LAYER_REBUILD >+ int m_rootLayerUpdateCount; >+#endif >+}; >+ >+ >+} // namespace WebCore >+ >+#endif // RenderLayerCompositor_h
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 23357
:
26775
|
26986
|
26988