diff options
-rw-r--r-- | WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp | 75 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/GraphicsLayerAndroid.h | 1 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.cpp | 69 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.h | 38 | ||||
-rw-r--r-- | WebCore/rendering/RenderLayerCompositor.cpp | 22 | ||||
-rw-r--r-- | WebKit/android/nav/WebView.cpp | 9 |
6 files changed, 174 insertions, 40 deletions
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index fd1c91a..b48ef49 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -218,26 +218,63 @@ 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) { - RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_client); - RenderLayer* renderLayer = backing->owningLayer(); - RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); - if (view->isPositioned() && view->style()->position() == FixedPosition) { - SkLength left, top, right, bottom; - left = convertLength(view->style()->left()); - top = convertLength(view->style()->top()); - right = convertLength(view->style()->right()); - bottom = convertLength(view->style()->bottom()); - // We need to pass the size of the element to compute the final fixed - // position -- we can't use the layer's size as it could possibly differs. - // We also have to use the visible overflow and not just the size, - // as some child elements could be overflowing. - int w = view->rightVisibleOverflow() - view->leftVisibleOverflow(); - int h = view->bottomVisibleOverflow() - view->topVisibleOverflow(); - m_contentLayer->setFixedPosition(left, top, right, bottom, w, h); - } + if (!m_client) + return; + + RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_client); + RenderLayer* renderLayer = backing->owningLayer(); + RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); + + // If we are a fixed position layer, just set it + if (view->isPositioned() && view->style()->position() == FixedPosition) { + SkLength left, top, right, bottom; + left = convertLength(view->style()->left()); + top = convertLength(view->style()->top()); + right = convertLength(view->style()->right()); + bottom = convertLength(view->style()->bottom()); + // We need to pass the size of the element to compute the final fixed + // position -- we can't use the layer's size as it could possibly differs. + // We also have to use the visible overflow and not just the size, + // as some child elements could be overflowing. + int w = view->rightVisibleOverflow() - view->leftVisibleOverflow(); + int h = view->bottomVisibleOverflow() - view->topVisibleOverflow(); + + m_contentLayer->setFixedPosition(left, top, right, bottom, w, h); } } @@ -419,6 +456,7 @@ 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()); @@ -882,6 +920,7 @@ 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 25f70b4..09f4181 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -110,6 +110,7 @@ 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 b0c2629..26372f0 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -49,10 +49,14 @@ 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_uniqueId(++gUniqueId), + m_relativeFixedLayer(0) { + m_deltaPosition.set(0, 0); m_angleTransform = 0; m_translation.set(0, 0); m_scale.set(1, 1); @@ -65,10 +69,14 @@ 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_uniqueId(layer.m_uniqueId), + m_relativeFixedLayer(0) { 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; @@ -100,10 +108,14 @@ 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_uniqueId(-1), + m_relativeFixedLayer(0) { + m_deltaPosition.set(0, 0); m_angleTransform = 0; m_translation.set(0, 0); m_scale.set(1, 1); @@ -245,9 +257,29 @@ const LayerAndroid* LayerAndroid::find(int x, int y) const /////////////////////////////////////////////////////////////////////////////// -void LayerAndroid::updatePositions(const SkRect& viewport) { - // apply the viewport to us - SkMatrix matrix; +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) { float x = 0; float y = 0; @@ -267,8 +299,25 @@ void LayerAndroid::updatePositions(const SkRect& viewport) { y = dy + h - m_fixedBottom.calcFloatValue(h) - m_fixedHeight; this->setPosition(x, y); - matrix.reset(); - } else { + } + + int count = this->countChildren(); + for (int i = 0; i < count; i++) { + this->getChild(i)->updateFixedLayersPositions(viewport); + } +} + +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 @@ -278,13 +327,13 @@ void LayerAndroid::updatePositions(const SkRect& viewport) { matrix.preRotate(m_angleTransform); } matrix.preScale(m_scale.fX, m_scale.fY); + this->setMatrix(matrix); } - this->setMatrix(matrix); // now apply it to our children int count = this->countChildren(); for (int i = 0; i < count; i++) { - this->getChild(i)->updatePositions(viewport); + this->getChild(i)->updatePositions(); } } diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 2554fb9..005ef3d 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -103,6 +103,14 @@ 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); @@ -126,14 +134,31 @@ public: void dumpLayers(FILE*, int indentLevel) const; void dumpToLog() const; - /** Call this with the current viewport (scrolling, zoom) to update its - position attribute, so that later calls like bounds() will report the - corrected position (assuming the layer had fixed-positioning). + /** 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. + + This call is recursive, so it should be called on the root of the + hierarchy. + */ + void updateFixedLayersPositions(const SkRect& viewPort); + + /** Call this to update the position attribute, so that later calls + like bounds() will report the corrected position. This call is recursive, so it should be called on the root of the hierarchy. */ - void updatePositions(const SkRect& viewPort); + void updatePositions(); void clipArea(SkTDArray<SkRect>* region) const; const LayerAndroid* find(int x, int y) const; @@ -160,6 +185,7 @@ private: bool m_haveClip; bool m_doRotation; bool m_isFixed; + bool m_isRelativeTo; bool m_backgroundColorSet; SkLength m_fixedLeft; @@ -168,6 +194,8 @@ private: SkLength m_fixedBottom; int m_fixedWidth; int m_fixedHeight; + int m_relativeFixedLayerID; + SkPoint m_deltaPosition; SkPoint m_translation; SkPoint m_scale; @@ -181,6 +209,8 @@ private: DrawExtra* m_extra; int m_uniqueId; + LayerAndroid* m_relativeFixedLayer; + typedef SkLayer INHERITED; }; diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index dc9b94d..a831a8b 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -702,7 +702,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, cons rebuildCompositingLayerTree(curLayer, childState, childList); } } - + if (layer->isStackingContext()) { if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { size_t listSize = posZOrderList->size(); @@ -712,7 +712,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, cons } } } - + if (layerBacking) { layerBacking->parentForSublayers()->setChildren(layerChildren); childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers()); @@ -927,6 +927,17 @@ 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; + } +#endif + return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers(); } @@ -944,13 +955,14 @@ 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) || +#else requiresCompositingForVideo(renderer) || requiresCompositingForCanvas(renderer) || requiresCompositingForPlugin(renderer) || - renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden || -#if PLATFORM(ANDROID) - (renderer->isPositioned() && renderer->style()->position() == FixedPosition) || #endif + renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden || clipsCompositingDescendants(layer) || requiresCompositingForAnimation(renderer); } diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 2c6b538..86f8797 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -294,7 +294,8 @@ void scrollRectOnScreen(const IntRect& rect) calcOurContentVisibleRect(&visible); #if USE(ACCELERATED_COMPOSITING) if (m_rootLayer) { - m_rootLayer->updatePositions(visible); + m_rootLayer->updateFixedLayersPositions(visible); + m_rootLayer->updatePositions(); visible = m_rootLayer->subtractLayers(visible); } #endif @@ -421,7 +422,8 @@ void drawExtras(SkCanvas* canvas, int extras) calcOurContentVisibleRect(&visible); // call this to be sure we've adjusted for any scrolling or animations // before we actually draw - m_rootLayer->updatePositions(visible); + m_rootLayer->updateFixedLayersPositions(visible); + m_rootLayer->updatePositions(); m_rootLayer->draw(canvas); #endif } @@ -548,7 +550,8 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer) LayerAndroid* layer = const_cast<LayerAndroid*>( m_frameCacheUI->rootLayer()); if (layer) { - layer->updatePositions(visible); + layer->updateFixedLayersPositions(visible); + layer->updatePositions(); } } #endif |