summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Roard <nicolas@android.com>2010-03-16 15:35:12 +0000
committerNicolas Roard <nicolas@android.com>2010-03-17 14:41:57 +0000
commit09cdf3e990745cfbcada2d0a49ef371029fc6a97 (patch)
treeac1e5f02cec6e463cb92d42742bcc4373ecf7770
parentb0c2f7b33106420933e04a3b0a69ca4d1d1b3fd8 (diff)
downloadexternal_webkit-09cdf3e990745cfbcada2d0a49ef371029fc6a97.zip
external_webkit-09cdf3e990745cfbcada2d0a49ef371029fc6a97.tar.gz
external_webkit-09cdf3e990745cfbcada2d0a49ef371029fc6a97.tar.bz2
Refactor how we set up the layers hierarchy when using fixed
composited layers, and fix the z-index position. Bug:2497910 Bug:2450006 We add a new COMPOSITED_FIXED_ELEMENTS define to isolate the changes in the webkit common code. We previously had a problem where the hierarchy of GraphicsLayer (i.e. the backed surfaces associated to the composited RenderLayer) was not reflecting that layers were children of a fixed layer. The workaround we currently have is not fully satisfactory, due to the way we draw layers on screen (in some cases layers were wrongly translated, see Bug:2497910). Instead, modifying the webkit common code simplify things a lot, and makes the patch more likely to be upstreamed to webkit, as it's now a reasonably well-delimited feature (use composited layers for fixed elements). What we do now is to consider fixed elements as a stacking context, which makes all layers children of such elements children too in the GraphicsLayer hierarchy, and modifying the offset of those children accordingly (in RenderLayer.cpp). In addition, we fixes the z-index bugs we had by signaling that there is a fixed element to its siblings, and turning the siblings as composited layers as well (so that the ordering works fully UI-side). Change-Id: I735c6c14d955ef54653f0053187d3495bef1f332
-rw-r--r--JavaScriptCore/wtf/Platform.h4
-rw-r--r--WebCore/config.h4
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp35
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.h1
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp46
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h23
-rw-r--r--WebCore/rendering/RenderLayer.cpp17
-rw-r--r--WebCore/rendering/RenderLayer.h10
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp61
9 files changed, 88 insertions, 113 deletions
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index f30ca49..a6ded58 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -824,6 +824,10 @@
#define ENABLE_TEXT_CARET 1
#endif
+#if !defined(ENABLE_COMPOSITED_FIXED_ELEMENTS)
+#define ENABLE_COMPOSITED_FIXED_ELEMENTS 0
+#endif
+
// ENABLE_ARCHIVE is an Android addition. We need this default value to allow
// us to build on Mac.
// FIXME: Upstream to webkit.org.
diff --git a/WebCore/config.h b/WebCore/config.h
index 4c7c2a9..75bc3b6 100644
--- a/WebCore/config.h
+++ b/WebCore/config.h
@@ -126,6 +126,10 @@
#undef ENABLE_APPLICATION_INSTALLED
#define ENABLE_APPLICATION_INSTALLED 1
+// Uses composited RenderLayers for fixed elements
+#undef ENABLE_COMPOSITED_FIXED_ELEMENTS // Disabled by default in Platform.h
+#define ENABLE_COMPOSITED_FIXED_ELEMENTS 1
+
#define FLATTEN_FRAMESET
#define FLATTEN_IFRAME
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index b48ef49..93469b0 100644
--- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -218,39 +218,6 @@ void GraphicsLayerAndroid::needsSyncChildren()
askForSync();
}
-void GraphicsLayerAndroid::syncFixedDescendants()
-{
- for (unsigned int i = 0; i < m_children.size(); i++)
- (static_cast<GraphicsLayerAndroid*>(m_children[i]))->syncFixedDescendants();
-
- if (!m_client)
- return;
-
- RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_client);
- RenderLayer* renderLayer = backing->owningLayer();
- RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
-
- // If we have an ancestor that is a fixed position layer, we need to
- // mark ourselve as a child of it, as the RenderLayer hierarchy only
- // keeps track of the z-order.
- // By calling setRelativeTo() we ensure that we will keep track of
- // the fixed layer we are relative to, and will be able to update
- // our position accordingly.
- RenderLayer* positionedParent = renderLayer->parent();
- while (positionedParent &&
- !(positionedParent->renderer()->isPositioned() &&
- positionedParent->renderer()->style()->position() == FixedPosition))
- positionedParent = positionedParent->parent();
-
- if (positionedParent && positionedParent->isComposited()) {
- RenderLayerBacking* positionedParentBacking = positionedParent->backing();
- GraphicsLayerAndroid* positionedParentLayer =
- static_cast<GraphicsLayerAndroid*>(positionedParentBacking->graphicsLayer());
- LayerAndroid* parentLayer = positionedParentLayer->contentLayer();
- m_contentLayer->setRelativeTo(parentLayer);
- }
-}
-
void GraphicsLayerAndroid::updateFixedPosition()
{
if (!m_client)
@@ -456,7 +423,6 @@ void GraphicsLayerAndroid::sendImmediateRepaint()
if (rootGraphicsLayer->m_frame
&& rootGraphicsLayer->m_frame->view()) {
LayerAndroid* copyLayer = new LayerAndroid(*m_contentLayer);
- copyLayer->ensureFixedLayersForDescendants(copyLayer);
TLOG("(%x) sendImmediateRepaint, copy the layer, (%.2f,%.2f => %.2f,%.2f)",
this, m_contentLayer->getSize().width(), m_contentLayer->getSize().height(),
copyLayer->getSize().width(), copyLayer->getSize().height());
@@ -920,7 +886,6 @@ void GraphicsLayerAndroid::syncCompositingState()
syncChildren();
syncMask();
syncPositionState();
- syncFixedDescendants();
if (!gPaused || WTF::currentTime() >= gPausedDelay)
repaintAll();
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 09f4181..25f70b4 100644
--- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -110,7 +110,6 @@ public:
virtual void setZPosition(float);
void askForSync();
- void syncFixedDescendants();
void syncPositionState();
void needsSyncChildren();
void syncChildren();
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
index 26372f0..c17a034 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -49,14 +49,10 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
m_haveClip(false),
m_doRotation(false),
m_isFixed(false),
- m_isRelativeTo(false),
- m_relativeFixedLayerID(0),
m_recordingPicture(0),
m_extra(0),
- m_uniqueId(++gUniqueId),
- m_relativeFixedLayer(0)
+ m_uniqueId(++gUniqueId)
{
- m_deltaPosition.set(0, 0);
m_angleTransform = 0;
m_translation.set(0, 0);
m_scale.set(1, 1);
@@ -69,14 +65,10 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
m_isRootLayer(layer.m_isRootLayer),
m_haveClip(layer.m_haveClip),
m_extra(0), // deliberately not copied
- m_uniqueId(layer.m_uniqueId),
- m_relativeFixedLayer(0)
+ m_uniqueId(layer.m_uniqueId)
{
m_doRotation = layer.m_doRotation;
m_isFixed = layer.m_isFixed;
- m_isRelativeTo = layer.m_isRelativeTo;
- m_relativeFixedLayerID = layer.m_relativeFixedLayerID;
- m_deltaPosition = layer.m_deltaPosition;
m_angleTransform = layer.m_angleTransform;
m_translation = layer.m_translation;
@@ -108,14 +100,10 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
m_haveClip(false),
m_doRotation(false),
m_isFixed(false),
- m_isRelativeTo(false),
- m_relativeFixedLayerID(0),
m_recordingPicture(picture),
m_extra(0),
- m_uniqueId(-1),
- m_relativeFixedLayer(0)
+ m_uniqueId(-1)
{
- m_deltaPosition.set(0, 0);
m_angleTransform = 0;
m_translation.set(0, 0);
m_scale.set(1, 1);
@@ -257,27 +245,6 @@ const LayerAndroid* LayerAndroid::find(int x, int y) const
///////////////////////////////////////////////////////////////////////////////
-void LayerAndroid::setRelativeTo(LayerAndroid* container) {
- ASSERT(container->m_isFixed);
- m_relativeFixedLayerID = container->m_uniqueId;
- m_isRelativeTo = true;
- m_deltaPosition = getPosition() - container->getPosition();
-}
-
-void LayerAndroid::ensureFixedLayersForDescendants(const LayerAndroid* rootLayer) {
- if (m_isRelativeTo && !m_relativeFixedLayer) {
- LayerAndroid* containerLayer = const_cast<LayerAndroid*>(
- rootLayer->findById(m_relativeFixedLayerID));
- if (containerLayer)
- m_relativeFixedLayer = containerLayer;
- }
-
- int count = countChildren();
- for (int i = 0; i < count; i++) {
- getChild(i)->ensureFixedLayersForDescendants(rootLayer);
- }
-}
-
void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport) {
if (m_isFixed) {
@@ -311,13 +278,6 @@ void LayerAndroid::updatePositions() {
// apply the viewport to us
SkMatrix matrix;
if (!m_isFixed) {
- // If we are defined as being relative to a fixed
- // layer, we need to update our position...
- if (m_isRelativeTo && m_relativeFixedLayer) {
- this->setPosition(m_relativeFixedLayer->getPosition().fX + m_deltaPosition.fX,
- m_relativeFixedLayer->getPosition().fY + m_deltaPosition.fY);
- }
-
// turn our fields into a matrix.
//
// TODO: this should happen in the caller, and we should remove these
diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h
index 005ef3d..247e902 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/WebCore/platform/graphics/android/LayerAndroid.h
@@ -103,14 +103,6 @@ public:
m_isFixed = true;
}
- /** Call that method to position the layer relative to another one.
- We can only be set relative to a fixed layer.
- The parameter is not refcounted -- we only save its ID as we
- need to reconnect with the correct layer once we copy the tree
- to the UI.
- */
- void setRelativeTo(LayerAndroid* container);
-
void setBackgroundColor(SkColor color);
void setMaskLayer(LayerAndroid*);
void setMasksToBounds(bool);
@@ -134,16 +126,6 @@ public:
void dumpLayers(FILE*, int indentLevel) const;
void dumpToLog() const;
- /** Call this to be sure all fixed descendants correctly have
- a pointer to their container layer before we try
- to update the positions. The fixed layer we point to is
- not refcounted (no need, it's already in the layers' tree).
-
- This call is recursive, so it should be called on the root of the
- hierarchy.
- */
- void ensureFixedLayersForDescendants(const LayerAndroid* rootLayer);
-
/** Call this with the current viewport (scrolling, zoom) to update
the position of the fixed layers.
@@ -185,7 +167,6 @@ private:
bool m_haveClip;
bool m_doRotation;
bool m_isFixed;
- bool m_isRelativeTo;
bool m_backgroundColorSet;
SkLength m_fixedLeft;
@@ -194,8 +175,6 @@ private:
SkLength m_fixedBottom;
int m_fixedWidth;
int m_fixedHeight;
- int m_relativeFixedLayerID;
- SkPoint m_deltaPosition;
SkPoint m_translation;
SkPoint m_scale;
@@ -209,8 +188,6 @@ private:
DrawExtra* m_extra;
int m_uniqueId;
- LayerAndroid* m_relativeFixedLayer;
-
typedef SkLayer INHERITED;
};
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index 6e51785..db079c7 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -1038,6 +1038,23 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
return;
}
}
+
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ // If fixed layers are composited, we need to look up for a parent layer
+ // that would be fixed, and compute the correct offset relative to it.
+ int intermediateX = 0;
+ int intermediateY = 0;
+ const RenderLayer* currLayer = this;
+ while ((currLayer = currLayer->parent())) {
+ if (currLayer->isComposited() && currLayer->isFixed()) {
+ xPos = x() + intermediateX;
+ yPos = y() + intermediateY;
+ return;
+ }
+ intermediateX += currLayer->x();
+ intermediateY += currLayer->y();
+ }
+#endif
RenderLayer* parentLayer;
if (position == AbsolutePosition || position == FixedPosition) {
diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h
index 3cdad3a..2c8d184 100644
--- a/WebCore/rendering/RenderLayer.h
+++ b/WebCore/rendering/RenderLayer.h
@@ -321,7 +321,15 @@ public:
// Get the enclosing stacking context for this layer. A stacking context is a layer
// that has a non-auto z-index.
RenderLayer* stackingContext() const;
- bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isRenderView(); }
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ bool isFixed() const { return renderer()->isPositioned() && renderer()->style()->position() == FixedPosition; }
+ // If fixed elements are composited, they will be containing children
+ bool isStackingContext() const {
+ return !hasAutoZIndex() || renderer()->isRenderView() || (isComposited() && isFixed());
+ }
+#else
+ bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isRenderView() ; }
+#endif
void dirtyZOrderLists();
void dirtyStackingContextZOrderLists();
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index a831a8b..2768461 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -67,6 +67,9 @@ struct CompositingState {
CompositingState(RenderLayer* compAncestor)
: m_compositingAncestor(compAncestor)
, m_subtreeIsCompositing(false)
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ , m_fixedSibling(false)
+#endif
#ifndef NDEBUG
, m_depth(0)
#endif
@@ -75,6 +78,9 @@ struct CompositingState {
RenderLayer* m_compositingAncestor;
bool m_subtreeIsCompositing;
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ bool m_fixedSibling;
+#endif
#ifndef NDEBUG
int m_depth;
#endif
@@ -496,7 +502,19 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
#endif
const bool willBeComposited = needsToBeComposited(layer);
+
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ // If we are a fixed layer, signal it to our siblings
+ if (layer->isFixed())
+ compositingState.m_fixedSibling = true;
+
+ if (!willBeComposited && compositingState.m_fixedSibling)
+ layer->setMustOverlapCompositedLayers(true);
+
+ if (willBeComposited || compositingState.m_fixedSibling) {
+#else
if (willBeComposited) {
+#endif
// Tell the parent it has compositing descendants.
compositingState.m_subtreeIsCompositing = true;
// This layer now acts as the ancestor for kids.
@@ -517,6 +535,25 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
ASSERT(!layer->m_zOrderListsDirty);
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ childState.m_fixedSibling = false;
+
+ // For the negative z-order, if we have a fixed layer
+ // we need to make all the siblings composited layers.
+ // Otherwise a negative layer (below the fixed layer) could
+ // still be drawn onto a higher z-order layer (e.g. the body)
+ // if not immediately intersecting with our fixed layer.
+ // So it's not enough here to only set m_fixedSibling for
+ // subsequent siblings as we do for the normal flow
+ // and positive z-order.
+ for (size_t j = 0; j < listSize; ++j) {
+ if ((negZOrderList->at(j))->isFixed()) {
+ childState.m_fixedSibling = true;
+ break;
+ }
+ }
+#endif
+
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = negZOrderList->at(i);
computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
@@ -537,6 +574,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
ASSERT(!layer->m_normalFlowListDirty);
if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
size_t listSize = normalFlowList->size();
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ childState.m_fixedSibling = false;
+#endif
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = normalFlowList->at(i);
computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
@@ -546,6 +586,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
size_t listSize = posZOrderList->size();
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ childState.m_fixedSibling = false;
+#endif
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = posZOrderList->at(i);
computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
@@ -927,14 +970,12 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
if (!m_hasAcceleratedCompositing || !layer->isSelfPaintingLayer())
return false;
-#if PLATFORM(ANDROID)
- // if an ancestor is fixed positionned, we need to be composited...
- RenderObject* renderer = layer->renderer();
- RenderObject* parent = renderer->parent();
- while (parent && (parent = renderer->parent())) {
- if (parent->isPositioned() && parent->style()->position() == FixedPosition)
- return true;
- renderer = parent;
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ // if an ancestor is fixed positioned, we need to be composited...
+ const RenderLayer* currLayer = layer;
+ while ((currLayer = currLayer->parent())) {
+ if (currLayer->isComposited() && currLayer->isFixed())
+ return true;
}
#endif
@@ -955,8 +996,8 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
// The root layer always has a compositing layer, but it may not have backing.
return (inCompositingMode() && layer->isRootLayer()) ||
requiresCompositingForTransform(renderer) ||
-#if PLATFORM(ANDROID)
- (renderer->isPositioned() && renderer->style()->position() == FixedPosition) ||
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ layer->isFixed() ||
#else
requiresCompositingForVideo(renderer) ||
requiresCompositingForCanvas(renderer) ||