2009-02-02 Simon Fraser <simon.fraser@apple.com>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Feb 2009 20:43:55 +0000 (20:43 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Feb 2009 20:43:55 +0000 (20:43 +0000)
        Reviewed by Dave Hyatt

        https://bugs.webkit.org/show_bug.cgi?id=23358

        Hook accelerated compositing into RenderLayer.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@40544 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/rendering/RenderLayer.cpp
WebCore/rendering/RenderLayer.h

index 1f98df5..938a5b7 100644 (file)
@@ -1,3 +1,88 @@
+2009-02-02  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
+
+        https://bugs.webkit.org/show_bug.cgi?id=23358
+
+        Hook accelerated compositing into RenderLayer.
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer):
+        (WebCore::RenderLayer::~RenderLayer):
+        Init and clean up backing and the hasCompositingDescendant bit.
+        
+        (WebCore::RenderLayer::compositor):
+        Shortcut to get to the RenderLayerCompositor.
+
+        (WebCore::RenderLayer::updateLayerPositions):
+        We need to let full repaints propagate to all compositing layers, and 
+        update the backing after layout here.
+        
+        (WebCore::RenderLayer::transparentAncestor):
+        (WebCore::transparencyClipBox):
+        (WebCore::RenderLayer::beginTransparencyLayers):
+        Account for the fact that opacity may be rendered via the compositing
+        layer sometimes.
+        
+        (WebCore::RenderLayer::addChild):
+        (WebCore::RenderLayer::removeChild):
+        (WebCore::RenderLayer::removeOnlyThisLayer):
+        Tell the compositor when the RenderLayer hierarchy changes.
+        
+        (WebCore::RenderLayer::scrollToOffset):
+        Update layer geometry after scrolling.
+        
+        (WebCore::RenderLayer::paintLayer):
+        We short-circuit painting on composited layers, because these layers
+        are painted on a callback from the compositing system.
+        
+        (WebCore::RenderLayer::hitTestLayer):
+        Only apply transforms if we are rendering them in software.
+        
+        (WebCore::RenderLayer::localBoundingBox):
+        (WebCore::RenderLayer::boundingBox):
+        (WebCore::RenderLayer::absoluteBoundingBox):
+        Refactor bounding box code that we can compute local, and ancestor-relative
+        bounding box, as well as absolute.
+        
+        (WebCore::RenderLayer::ensureBacking):
+        (WebCore::RenderLayer::clearBacking):
+        RenderLayerBacking creation and destruction.
+        
+        (WebCore::RenderLayer::setParent):
+        Tell the compositor when the RenderLayer hierarchy changes.
+
+        (WebCore::RenderLayer::dirtyZOrderLists):
+        (WebCore::RenderLayer::dirtyStackingContextZOrderLists):
+        (WebCore::RenderLayer::dirtyOverflowList):
+        When the z-order and overflow lists change, we need to tell the
+        compositor that the composited layers need to be rejiggered soon.
+        
+        (WebCore::RenderLayer::updateZOrderLists):
+        Whitespace cleanup.
+        
+        (WebCore::RenderLayer::setBackingNeedsRepaint):
+        (WebCore::RenderLayer::setBackingNeedsRepaintInRect):
+        Dirty composited layer contents for painting.
+        
+        (WebCore::RenderLayer::styleChanged):
+        Update the layer backing after style changes.
+
+        * rendering/RenderLayer.h:
+        (WebCore::RenderLayer::isComposited):
+        (WebCore::RenderLayer::backing):
+        Accessors for testing and getting the backing for this RenderLayer.
+        
+        (WebCore::RenderLayer::paintsWithTransparency):
+        (WebCore::RenderLayer::paintsWithTransform):
+        Transform and opacity can be applied via the compositing layer, or rendered
+        in software. These methods tell us if we need to account for them in the
+        non-compositing path.
+        
+        (WebCore::RenderLayer::hasCompositingDescendant):
+        (WebCore::RenderLayer::setHasCompositingDescendant):
+        Maintain a bit to tell if this layer has composited descendants.
+
 2009-02-03  Simon Fraser  <simon.fraser@apple.com>
 
         Reviewed by Dave Hyatt
index 01c4928..ec82fce 100644 (file)
@@ -44,7 +44,9 @@
 #include "config.h"
 #include "RenderLayer.h"
 
+#include "CString.h"
 #include "CSSPropertyNames.h"
+#include "CSSStyleSelector.h"
 #include "Document.h"
 #include "EventHandler.h"
 #include "EventNames.h"
 #include "Scrollbar.h"
 #include "ScrollbarTheme.h"
 #include "SelectionController.h"
+#include "TransformationMatrix.h"
 #include "TranslateTransformOperation.h"
 #include <wtf/StdLibExtras.h>
 
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerBacking.h"
+#include "RenderLayerCompositor.h"
+#endif
+
 #if ENABLE(SVG)
 #include "SVGNames.h"
 #endif
@@ -156,6 +164,9 @@ RenderLayer::RenderLayer(RenderBox* renderer)
     , m_hasVisibleContent(false)
     , m_visibleDescendantStatusDirty(false)
     , m_hasVisibleDescendant(false)
+#if USE(ACCELERATED_COMPOSITING)
+    , m_hasCompositingDescendant(false)
+#endif
     , m_marquee(0)
     , m_staticX(0)
     , m_staticY(0)
@@ -163,6 +174,9 @@ RenderLayer::RenderLayer(RenderBox* renderer)
     , m_reflection(0)
     , m_scrollCorner(0)
     , m_resizer(0)
+#if USE(ACCELERATED_COMPOSITING)
+    , m_backing(0)
+#endif
 {
     if (!renderer->firstChild() && renderer->style()) {
         m_visibleContentStatusDirty = false;
@@ -188,6 +202,10 @@ RenderLayer::~RenderLayer()
     delete m_overflowList;
     delete m_marquee;
 
+#if USE(ACCELERATED_COMPOSITING)
+    clearBacking();
+#endif
+    
     // Make sure we have no lingering clip rects.
     ASSERT(!m_clipRects);
     
@@ -204,11 +222,25 @@ RenderLayer::~RenderLayer()
         m_resizer->destroy();
 }
 
+#if USE(ACCELERATED_COMPOSITING)
+RenderLayerCompositor* RenderLayer::compositor() const
+{
+    return renderer()->view()->compositor();
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
 void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
 {
     if (doFullRepaint) {
         renderer()->repaint();
+#if USE(ACCELERATED_COMPOSITING)
+        checkForRepaint = false;
+        // We need the full repaint to propagate to child layers if we are hardware compositing.
+        if (!compositor()->inCompositingMode())
+            doFullRepaint = false;
+#else
         checkForRepaint = doFullRepaint = false;
+#endif
     }
     
     updateLayerPosition(); // For relpositioned layers or non-positioned layers,
@@ -259,6 +291,11 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
 
     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
         child->updateLayerPositions(doFullRepaint, checkForRepaint);
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (isComposited())
+        backing()->updateAfterLayout();
+#endif
         
     // With all our children positioned, now update our marquee if we need to.
     if (m_marquee)
@@ -495,12 +532,18 @@ bool RenderLayer::isTransparent() const
     return renderer()->isTransparent() || renderer()->hasMask();
 }
 
-RenderLayer*
-RenderLayer::transparentAncestor()
+RenderLayer* RenderLayer::transparentPaintingAncestor()
 {
-    RenderLayer* curr = parent();
-    for ( ; curr && !curr->isTransparent(); curr = curr->parent()) { }
-    return curr;
+    if (isComposited())
+        return 0;
+
+    for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
+        if (curr->isComposited())
+            return 0;
+        if (curr->isTransparent())
+            return curr;
+    }
+    return 0;
 }
 
 static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
@@ -509,16 +552,16 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor
     // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
     // would be better to respect clips.
     
-    TransformationMatrix* t = l->transform();
-    if (t && rootLayer != l) {
+    if (rootLayer != l && l->paintsWithTransform()) {
         // 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.
         int x = 0;
         int y = 0;
         l->convertToLayerCoords(rootLayer, x, y);
+
         TransformationMatrix transform;
         transform.translate(x, y);
-        transform = *t * transform;
+        transform = *l->transform() * transform;
         transform = transform * enclosingTransform;
 
         // We now have a transform that will produce a rectangle in our view's space.
@@ -552,14 +595,14 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor
 
 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer)
 {
-    if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
+    if (p->paintingDisabled() || (paintsWithTransparency() && m_usedTransparency))
         return;
     
-    RenderLayer* ancestor = transparentAncestor();
+    RenderLayer* ancestor = transparentPaintingAncestor();
     if (ancestor)
         ancestor->beginTransparencyLayers(p, rootLayer);
     
-    if (isTransparent()) {
+    if (paintsWithTransparency()) {
         m_usedTransparency = true;
         p->save();
         p->clip(transparencyClipBox(TransformationMatrix(), this, rootLayer));
@@ -616,10 +659,18 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
     child->updateVisibilityStatus();
     if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
         childVisibilityChanged(true);
+    
+#if USE(ACCELERATED_COMPOSITING)
+    compositor()->layerWasAdded(this, child);
+#endif
 }
 
 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
 {
+#if USE(ACCELERATED_COMPOSITING)
+    compositor()->layerWillBeRemoved(this, oldChild);
+#endif
+
     // remove the child
     if (oldChild->previousSibling())
         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
@@ -656,6 +707,10 @@ void RenderLayer::removeOnlyThisLayer()
     if (!m_parent)
         return;
     
+#if USE(ACCELERATED_COMPOSITING)
+    compositor()->layerWillBeRemoved(m_parent, this);
+#endif
+
     // Dirty the clip rects.
     clearClipRectsIncludingDescendants();
 
@@ -833,6 +888,11 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
     // Update the positions of our child layers.
     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
         child->updateLayerPositions(false, false);
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (isComposited())
+        m_backing->updateGraphicsLayerGeometry();
+#endif
     
     RenderView* view = renderer()->view();
     
@@ -1656,6 +1716,12 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
                         const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
                         RenderObject* paintingRoot, bool appliedTransform, bool temporaryClipRects)
 {
+#if USE(ACCELERATED_COMPOSITING)
+    // Composited RenderLayers are painted via the backing's paintIntoLayer().
+    if (isComposited() && !backing()->paintingGoesToWindow())
+        return;
+#endif
+
     // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
     // will do a full repaint().
@@ -1666,11 +1732,11 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
     if (!renderer()->opacity())
         return;
 
-    if (isTransparent())
+    if (paintsWithTransparency())
         haveTransparency = true;
 
     // Apply a transform if we have one.  A reflection is considered to be a transform, since it is a flip and a translate.
-    if (m_transform && !appliedTransform) {
+    if (paintsWithTransform() && !appliedTransform) {
         // If the transform can't be inverted, then don't paint anything.
         if (!m_transform->isInvertible())
             return;
@@ -1712,7 +1778,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
 
         // Now do a paint with the root layer shifted to be us.
         paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), haveTransparency, paintRestriction, paintingRoot, true, temporaryClipRects);
-        
+
         p->restore();
         
         // Restore the clip.
@@ -1738,8 +1804,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
     int ty = y - renderer()->y();
                              
     // Ensure our lists are up-to-date.
-    updateZOrderLists();
-    updateOverflowList();
+    updateLayerListsIfNeeded();
 
     bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
     bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
@@ -1836,7 +1901,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
     }
 
     // End our transparency layer
-    if (isTransparent() && m_usedTransparency) {
+    if (haveTransparency && m_usedTransparency) {
         p->endTransparencyLayer();
         p->restore();
         m_usedTransparency = false;
@@ -1894,7 +1959,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
                                        const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform)
 {
     // Apply a transform if we have one.
-    if (m_transform && !appliedTransform) {
+    if (paintsWithTransform() && !appliedTransform) {
         // If the transform can't be inverted, then don't hit test this layer at all.
         if (!m_transform->isInvertible())
             return 0;
@@ -1930,8 +1995,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
     calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
     
     // Ensure our lists are up-to-date.
-    updateZOrderLists();
-    updateOverflowList();
+    updateLayerListsIfNeeded();
 
     // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
     // we are done and can return it.
@@ -2205,7 +2269,7 @@ bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect
     return boundingBox(rootLayer).intersects(damageRect);
 }
 
-IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
+IntRect RenderLayer::localBoundingBox() const
 {
     // There are three special cases we need to consider.
     // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
@@ -2228,7 +2292,7 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
         int left = firstBox->xPos();
         for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
             left = min(left, curr->xPos());
-        result = IntRect(m_x + left, m_y + (top - renderer()->y()), width(), bottom - top);
+        result = IntRect(left, (top - renderer()->y()), width(), bottom - top);
     } else if (renderer()->isTableRow()) {
         // Our bounding box is just the union of all of our cells' border/overflow rects.
         for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
@@ -2240,7 +2304,6 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
                     result.unite(overflowRect);
             }
         }
-        result.move(m_x, m_y);
     } else {
         if (renderer()->hasMask())
             result = renderer()->maskClipRect();
@@ -2251,24 +2314,31 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
             if (bbox != overflowRect)
                 result.unite(overflowRect);
         }
-
-        // We have to adjust the x/y of this result so that it is in the coordinate space of the layer.
-        result.move(m_x, m_y);
     }
-    
-    // Convert the bounding box to an absolute position.  We can do this easily by looking at the delta
-    // between the bounding box's xpos and our layer's xpos and then applying that to the absolute layerBounds
-    // passed in.
-    int absX = 0, absY = 0;
-    convertToLayerCoords(rootLayer, absX, absY);
-    result.move(absX - m_x, absY - m_y);
+
     RenderView* view = renderer()->view();
     ASSERT(view);
     if (view)
-        result.inflate(view->maximalOutlineSize());
+        result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
+
+    return result;
+}
+
+IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
+{    
+    IntRect result = localBoundingBox();
+
+    int deltaX = 0, deltaY = 0;
+    convertToLayerCoords(ancestorLayer, deltaX, deltaY);
+    result.move(deltaX, deltaY);
     return result;
 }
 
+IntRect RenderLayer::absoluteBoundingBox() const
+{
+    return boundingBox(root());
+}
+
 void RenderLayer::clearClipRectsIncludingDescendants()
 {
     if (!m_clipRects)
@@ -2291,6 +2361,37 @@ void RenderLayer::clearClipRects()
     }
 }
 
+#if USE(ACCELERATED_COMPOSITING)
+RenderLayerBacking* RenderLayer::ensureBacking()
+{
+    m_backing.adopt(new RenderLayerBacking(this));
+    return m_backing.get();
+}
+
+void RenderLayer::clearBacking()
+{
+    m_backing.clear();
+}
+#endif
+
+void RenderLayer::setParent(RenderLayer* parent)
+{
+    if (parent == m_parent)
+        return;
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_parent && compositor())
+        compositor()->layerWillBeRemoved(m_parent, this);
+#endif
+    
+    m_parent = parent;
+    
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_parent)
+        compositor()->layerWasAdded(m_parent, this);
+#endif
+}
+
 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
 {
     if (!obj1 || !obj2)
@@ -2386,6 +2487,11 @@ void RenderLayer::dirtyZOrderLists()
     if (m_negZOrderList)
         m_negZOrderList->clear();
     m_zOrderListsDirty = true;
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (compositor())
+        compositor()->setCompositingLayersNeedUpdate();
+#endif
 }
 
 void RenderLayer::dirtyStackingContextZOrderLists()
@@ -2400,13 +2506,18 @@ void RenderLayer::dirtyOverflowList()
     if (m_overflowList)
         m_overflowList->clear();
     m_overflowListDirty = true;
+
+#if USE(ACCELERATED_COMPOSITING)
+    if (compositor())
+        compositor()->setCompositingLayersNeedUpdate();
+#endif
 }
 
 void RenderLayer::updateZOrderLists()
 {
     if (!isStackingContext() || !m_zOrderListsDirty)
         return;
-        
+
     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
         if (!m_reflection || reflectionLayer() != child)
             child->collectLayers(m_posZOrderList, m_negZOrderList);
@@ -2414,6 +2525,7 @@ void RenderLayer::updateZOrderLists()
     // Sort the two lists.
     if (m_posZOrderList)
         std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
+
     if (m_negZOrderList)
         std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
 
@@ -2465,6 +2577,19 @@ void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderL
     }
 }
 
+void RenderLayer::updateLayerListsIfNeeded()
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (compositor()->inCompositingMode()) {
+        if ((isStackingContext() && m_zOrderListsDirty) || m_overflowListDirty)
+            compositor()->updateCompositingLayers(this);
+        return;
+    }
+#endif
+    updateZOrderLists();
+    updateOverflowList();
+}
+
 void RenderLayer::repaintIncludingDescendants()
 {
     renderer()->repaint();
@@ -2472,6 +2597,40 @@ void RenderLayer::repaintIncludingDescendants()
         curr->repaintIncludingDescendants();
 }
 
+#if USE(ACCELERATED_COMPOSITING)
+void RenderLayer::setBackingNeedsRepaint()
+{
+    ASSERT(isComposited());
+    if (backing()->paintingGoesToWindow()) {
+        // If we're trying to repaint the placeholder document layer, propagate the
+        // repaint to the native view system.
+        RenderView* view = renderer()->view();
+        if (view)
+            view->repaintViewRectangle(absoluteBoundingBox());
+    } else
+        backing()->setContentsNeedDisplay();
+}
+
+void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r)
+{
+    ASSERT(isComposited());
+    if (backing()->paintingGoesToWindow()) {
+        // If we're trying to repaint the placeholder document layer, propagate the
+        // repaint to the native view system.
+        IntRect absRect(r);
+        int x = 0;
+        int y = 0;
+        convertToLayerCoords(root(), x, y);
+        absRect.move(x, y);
+
+        RenderView* view = renderer()->view();
+        if (view)
+            view->repaintViewRectangle(absRect);
+    } else
+        backing()->setContentsNeedDisplayInRect(r);
+}
+#endif
+
 bool RenderLayer::shouldBeOverflowOnly() const
 {
     return (renderer()->hasOverflowClip() || renderer()->hasReflection()) && 
@@ -2481,7 +2640,7 @@ bool RenderLayer::shouldBeOverflowOnly() const
            !isTransparent();
 }
 
-void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle*)
+void RenderLayer::styleChanged(RenderStyle::Diff diff, const RenderStyle*)
 {
     bool isOverflowOnly = shouldBeOverflowOnly();
     if (isOverflowOnly != m_isOverflowOnly) {
@@ -2519,6 +2678,15 @@ void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle*)
     
     updateScrollCornerStyle();
     updateResizerStyle();
+
+#if USE(ACCELERATED_COMPOSITING)
+    updateTransform();
+
+    if (compositor()->updateLayerCompositingState(this, diff))
+        compositor()->setCompositingLayersNeedUpdate();
+#else
+    UNUSED_PARAM(diff);
+#endif
 }
 
 void RenderLayer::updateScrollCornerStyle()
index 26f5f08..7f85df5 100644 (file)
@@ -51,7 +51,6 @@
 
 namespace WebCore {
 
-class TransformationMatrix;
 class CachedResource;
 class HitTestRequest;
 class HitTestResult;
@@ -64,6 +63,12 @@ class RenderTable;
 class RenderText;
 class RenderView;
 class Scrollbar;
+class TransformationMatrix;
+
+#if USE(ACCELERATED_COMPOSITING)
+class RenderLayerBacking;
+class RenderLayerCompositor;
+#endif
 
 class ClipRects {
 public:
@@ -199,6 +204,13 @@ public:
 
     void repaintIncludingDescendants();
 
+#if USE(ACCELERATED_COMPOSITING)
+    // Indicate that the layer contents need to be repainted. Only has an effect
+    // if layer compositing is being used,
+    void setBackingNeedsRepaint();
+    void setBackingNeedsRepaintInRect(const IntRect& r); // r is in the coordinate space of the layer's render object
+#endif
+
     void styleChanged(RenderStyle::Diff, const RenderStyle*);
 
     RenderMarquee* marquee() const { return m_marquee; }
@@ -209,7 +221,7 @@ public:
     bool requiresSlowRepaints() const;
 
     bool isTransparent() const;
-    RenderLayer* transparentAncestor();
+    RenderLayer* transparentPaintingAncestor();
     void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer);
 
     bool hasReflection() const { return renderer()->hasReflection(); }
@@ -287,6 +299,10 @@ public:
     void resize(const PlatformMouseEvent&, const IntSize&);
     bool inResizeMode() const { return m_inResizeMode; }
     void setInResizeMode(bool b) { m_inResizeMode = b; }
+
+#if USE(ACCELERATED_COMPOSITING)
+    RenderLayerCompositor* compositor() const;
+#endif
     
     void updateLayerPosition();
     void updateLayerPositions(bool doFullRepaint = false, bool checkForRepaint = true);
@@ -352,8 +368,12 @@ public:
 
     bool intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const;
 
-    // Returns a bounding box for this layer only.
+    // Bounding box relative to some ancestor layer.
     IntRect boundingBox(const RenderLayer* rootLayer) const;
+    // Bounding box in the coordinates of this layer.
+    IntRect localBoundingBox() const;
+    // Bounding box relative to the root.
+    IntRect absoluteBoundingBox() const;
 
     void updateHoverActiveState(const HitTestRequest&, HitTestResult&);
 
@@ -367,6 +387,7 @@ public:
     void setStaticY(int staticY) { m_staticY = staticY; }
 
     bool hasTransform() const { return renderer()->hasTransform(); }
+    // Note that this transform has the transform-origin baked in.
     TransformationMatrix* transform() const { return m_transform.get(); }
 
     void destroy(RenderArena*);
@@ -378,6 +399,25 @@ public:
     // Overridden to prevent the normal delete from being called.
     void operator delete(void*, size_t);
 
+#if USE(ACCELERATED_COMPOSITING)
+    bool isComposited() const { return m_backing != 0; }
+    RenderLayerBacking* backing() const { return m_backing; }
+    RenderLayerBacking* ensureBacking();
+    void clearBacking();
+#else
+    bool isComposited() const { return false; }
+#endif
+
+    bool paintsWithTransparency() const
+    {
+        return isTransparent() && !isComposited();
+    }
+
+    bool paintsWithTransform() const
+    {
+        return transform() && !isComposited();
+    }
+
 private:
     // The normal operator new is disallowed on all render objects.
     void* operator new(size_t) throw();
@@ -385,16 +425,19 @@ private:
 private:
     void setNextSibling(RenderLayer* next) { m_next = next; }
     void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
-    void setParent(RenderLayer* parent) { m_parent = parent; }
+    void setParent(RenderLayer* parent);
     void setFirstChild(RenderLayer* first) { m_first = first; }
     void setLastChild(RenderLayer* last) { m_last = last; }
 
     void collectLayers(Vector<RenderLayer*>*&, Vector<RenderLayer*>*&);
 
+    void updateLayerListsIfNeeded();
+    
     void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
                     bool haveTransparency, PaintRestriction, RenderObject* paintingRoot,
                     bool appliedTransform = false, bool temporaryClipRects = false);
     RenderLayer* hitTestLayer(RenderLayer* rootLayer, const HitTestRequest&, HitTestResult&, const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform = false);
+
     void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
 
     bool shouldBeOverflowOnly() const;
@@ -424,7 +467,16 @@ private:
     void updateScrollCornerStyle();
     void updateResizerStyle();
 
-protected:   
+#if USE(ACCELERATED_COMPOSITING)    
+    bool hasCompositingDescendant() const { return m_hasCompositingDescendant; }
+    void setHasCompositingDescendant(bool b)  { m_hasCompositingDescendant = b; }
+#endif
+
+private:
+    friend class RenderLayerBacking;
+    friend class RenderLayerCompositor;
+
+protected:
     RenderBox* m_renderer;
 
     RenderLayer* m_parent;
@@ -501,6 +553,10 @@ protected:
     bool m_visibleDescendantStatusDirty : 1;
     bool m_hasVisibleDescendant : 1;
 
+#if USE(ACCELERATED_COMPOSITING)
+    bool m_hasCompositingDescendant : 1;
+#endif
+
     RenderMarquee* m_marquee; // Used by layers with overflow:marquee
     
     // Cached normal flow values for absolute positioned elements with static left/top values.
@@ -515,6 +571,10 @@ protected:
     // Renderers to hold our custom scroll corner and resizer.
     RenderScrollbarPart* m_scrollCorner;
     RenderScrollbarPart* m_resizer;
+
+#if USE(ACCELERATED_COMPOSITING)
+    OwnPtr<RenderLayerBacking> m_backing;
+#endif
 };
 
 } // namespace WebCore