diff options
author | Chris Craik <ccraik@google.com> | 2012-03-07 14:12:30 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-03-07 14:12:30 -0800 |
commit | bb78287b9586253a7ae7d5d8b1a7a0326643c7ce (patch) | |
tree | 1769abd5392a49b6e1e812c4f8eb0f5326a454df /Source | |
parent | d62f390122ad9098adea5ba31b9eee83e2129aa6 (diff) | |
parent | 0de5188ef06efbbf15051a6ea07ba970253c569c (diff) | |
download | external_webkit-bb78287b9586253a7ae7d5d8b1a7a0326643c7ce.zip external_webkit-bb78287b9586253a7ae7d5d8b1a7a0326643c7ce.tar.gz external_webkit-bb78287b9586253a7ae7d5d8b1a7a0326643c7ce.tar.bz2 |
Merge "UI-side layer merging"
Diffstat (limited to 'Source')
12 files changed, 348 insertions, 129 deletions
diff --git a/Source/WebCore/platform/graphics/android/FixedLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/FixedLayerAndroid.cpp index 8642f8e..67e2342 100644 --- a/Source/WebCore/platform/graphics/android/FixedLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FixedLayerAndroid.cpp @@ -71,9 +71,9 @@ LayerAndroid* FixedLayerAndroid::updateFixedLayerPosition(SkRect viewport, return iframeLayer; } -void FixedLayerAndroid::contentDraw(SkCanvas* canvas) +void FixedLayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) { - LayerAndroid::contentDraw(canvas); + LayerAndroid::contentDraw(canvas, style); if (TilesManager::instance()->getShowVisualIndicator()) { SkPaint paint; paint.setARGB(80, 255, 0, 0); diff --git a/Source/WebCore/platform/graphics/android/FixedLayerAndroid.h b/Source/WebCore/platform/graphics/android/FixedLayerAndroid.h index 4f0f7c2..2578075 100644 --- a/Source/WebCore/platform/graphics/android/FixedLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/FixedLayerAndroid.h @@ -95,7 +95,7 @@ public: virtual LayerAndroid* updateFixedLayerPosition(SkRect viewPort, LayerAndroid* parentIframeLayer); - virtual void contentDraw(SkCanvas*); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); virtual void dumpLayer(FILE*, int indentLevel) const; diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 80325e2..0ee6443 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -521,6 +521,8 @@ void GraphicsLayerAndroid::updateScrollingLayers() if (layerNeedsOverflow) { ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); m_foregroundLayer = new ScrollableLayerAndroid(layer); + + // TODO: can clip layer be set to not intrinsically composited? m_foregroundClipLayer = new LayerAndroid(layer); m_foregroundClipLayer->setMasksToBounds(true); m_foregroundClipLayer->addChild(m_foregroundLayer); @@ -1029,6 +1031,12 @@ void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list) void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly() { + if (m_contentLayer) { + RenderLayer* renderLayer = renderLayerFromClient(m_client); + int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true; + m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited); + } + updateScrollingLayers(); updateFixedPosition(); syncChildren(); diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp index f58d648..7453a24 100644 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ b/Source/WebCore/platform/graphics/android/Layer.cpp @@ -158,10 +158,6 @@ void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const { /////////////////////////////////////////////////////////////////////////////// -void Layer::onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra) { -// SkDebugf("----- no onDraw for %p\n", this); -} - #include "SkString.h" void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) { @@ -193,7 +189,7 @@ void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) canvas->concat(tmp); } - onDraw(canvas, opacity, extra); + onDraw(canvas, opacity, extra, FlattenedLayers); #ifdef DEBUG_DRAW_LAYER_BOUNDS { diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h index 9165307..b45f70d 100644 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ b/Source/WebCore/platform/graphics/android/Layer.h @@ -151,8 +151,9 @@ public: virtual bool contentIsScrollable() const { return false; } + enum PaintStyle { MergedLayers, UnmergedLayers, FlattenedLayers }; protected: - virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra); + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style) {} bool m_hasOverflowChildren; diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index e3c3b04..aaa57d6 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -25,6 +25,12 @@ #define LAYER_DEBUG // Add diagonals for debugging #undef LAYER_DEBUG +#define DISABLE_LAYER_MERGE +#undef DISABLE_LAYER_MERGE + +#define LAYER_GROUPING_DEBUG +#undef LAYER_GROUPING_DEBUG + #include <cutils/log.h> #include <wtf/text/CString.h> #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) @@ -76,6 +82,7 @@ LayerAndroid::LayerAndroid(RenderLayer* owner, SubclassType subclassType) : Laye m_type(LayerAndroid::WebCoreLayer), m_subclassType(subclassType), m_hasText(true), + m_intrinsicallyComposited(true), m_layerGroup(0) { m_backgroundColor = 0; @@ -95,7 +102,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer, SubclassType subclassType) m_uniqueId(layer.m_uniqueId), m_owningLayer(layer.m_owningLayer), m_type(LayerAndroid::UILayer), - m_hasText(true), + m_hasText(layer.m_hasText), + m_intrinsicallyComposited(layer.m_intrinsicallyComposited), m_layerGroup(0) { m_imageCRC = layer.m_imageCRC; @@ -135,8 +143,6 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer, SubclassType subclassType) m_animations.add(it->first, it->second); } - m_hasText = layer.m_hasText; - #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid - recopy (UI)"); ClassTracker::instance()->add(this); @@ -179,6 +185,7 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_type(LayerAndroid::NavCacheLayer), m_subclassType(LayerAndroid::StandardLayer), m_hasText(true), + m_intrinsicallyComposited(true), m_layerGroup(0) { m_backgroundColor = 0; @@ -619,22 +626,6 @@ void LayerAndroid::showLayer(int indent) this->getChild(i)->showLayer(indent + 1); } -void LayerAndroid::setIsPainting(Layer* drawingTree) -{ - XLOG("setting layer %p as painting, needs texture %d, drawing tree %p", - this, needsTexture(), drawingTree); - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->setIsPainting(drawingTree); - - - LayerAndroid* drawingLayer = 0; - if (drawingTree) - drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId()); - - obtainTextureForPainting(drawingLayer); -} - void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree) { int count = this->countChildren(); @@ -690,49 +681,90 @@ bool LayerAndroid::updateWithLayer(LayerAndroid* layer) return false; } -void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer) +static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) { - if (!needsTexture()) - return; - - // layer group init'd with previous drawing layer - m_layerGroup->initializeGroup(this, m_dirtyRegion, drawingLayer); - m_dirtyRegion.setEmpty(); + return a->zValue() > b->zValue(); } - -static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) +bool LayerAndroid::canJoinGroup(LayerGroup* group) { - return a->zValue() > b->zValue(); +#if DISABLE_LAYER_MERGE + return false; +#else + // returns true if the layer can be merged onto the layergroup + if (!group) + return false; + + LayerAndroid* lastLayer = group->getFirstLayer(); + + // isolate non-tiled layers + // TODO: remove this check so that multiple tiled layers with a invisible + // one inbetween can be merged + if (!needsTexture() || !lastLayer->needsTexture()) + return false; + + // isolate clipped layers + // TODO: paint correctly with clip when merged + if (m_haveClip || lastLayer->m_haveClip) + return false; + + // isolate intrinsically composited layers + if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited) + return false; + + // TODO: investigate potential for combining transformed layers + if (!m_drawTransform.isIdentityOrTranslation() + || !lastLayer->m_drawTransform.isIdentityOrTranslation()) + return false; + + // currently, we don't group zoomable with non-zoomable layers (unless the + // group or the layer doesn't need a texture) + if (group->needsTexture() && needsTexture() && m_hasText != group->hasText()) + return false; + + // TODO: compare other layer properties - fixed? overscroll? transformed? + return true; +#endif } -void LayerAndroid::assignGroups(Vector<LayerGroup*>* allGroups) +void LayerAndroid::assignGroups(LayerMergeState* mergeState) { - // recurse through layers in draw order - // if a layer needs isolation (e.g. has animation, is fixed, overflow:scroll) - // create new layer group on the stack + // recurse through layers in draw order, and merge layers when able - bool needsIsolation = false; - LayerGroup* currentLayerGroup = 0; - if (!allGroups->isEmpty()) - currentLayerGroup = allGroups->at(0); + bool needNewGroup = !mergeState->currentLayerGroup + || mergeState->nonMergeNestedLevel > 0 + || !canJoinGroup(mergeState->currentLayerGroup); - // TODO: compare layer with group on top of stack - fixed? overscroll? transformed? - needsIsolation = isFixed() || (m_animations.size() != 0); + if (needNewGroup) { + mergeState->currentLayerGroup = new LayerGroup(); + mergeState->groupList->append(mergeState->currentLayerGroup); + } + +#ifdef LAYER_GROUPING_DEBUG + XLOGC("%*slayer %p(%d) rl %p %s group %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", + 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, + needNewGroup ? "NEW" : "joins", mergeState->currentLayerGroup, + m_isFixed, m_animations.size() != 0, + m_intrinsicallyComposited, + m_haveClip, + contentIsScrollable()); +#endif - if (!currentLayerGroup || needsIsolation || true) { - currentLayerGroup = new LayerGroup(); - allGroups->append(currentLayerGroup); + mergeState->currentLayerGroup->addLayer(this, m_drawTransform); + m_layerGroup = mergeState->currentLayerGroup; + + if (m_haveClip || contentIsScrollable() || isFixed()) { + // disable layer merging within the children of these layer types + mergeState->nonMergeNestedLevel++; } - currentLayerGroup->addLayer(this); - m_layerGroup = currentLayerGroup; // pass the layergroup through children in drawing order, so that they may // attach themselves (and paint on it) if possible, or ignore it and create // a new one if not int count = this->countChildren(); if (count > 0) { + mergeState->depth++; Vector <LayerAndroid*> sublayers; for (int i = 0; i < count; i++) sublayers.append(getChild(i)); @@ -740,7 +772,16 @@ void LayerAndroid::assignGroups(Vector<LayerGroup*>* allGroups) // sort for the transparency std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); for (int i = 0; i < count; i++) - sublayers[i]->assignGroups(allGroups); + sublayers[i]->assignGroups(mergeState); + mergeState->depth--; + } + + if (m_haveClip || contentIsScrollable() || isFixed()) { + // re-enable joining + mergeState->nonMergeNestedLevel--; + + // disallow layers painting after to join with this group + mergeState->currentLayerGroup = 0; } } @@ -789,7 +830,7 @@ IntRect LayerAndroid::visibleArea() return rect; } -bool LayerAndroid::drawCanvas(SkCanvas* canvas) +bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style) { if (!m_visible) return false; @@ -808,11 +849,14 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas) SkMatrix canvasMatrix = canvas->getTotalMatrix(); matrix.postConcat(canvasMatrix); canvas->setMatrix(matrix); - onDraw(canvas, m_drawOpacity, 0); + onDraw(canvas, m_drawOpacity, 0, style); } + if (!drawChildren) + return false; + // When the layer is dirty, the UI thread should be notified to redraw. - askScreenUpdate |= drawChildrenCanvas(canvas); + askScreenUpdate |= drawChildrenCanvas(canvas, style); m_atomicSync.lock(); if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective()) addDirtyArea(); @@ -843,7 +887,7 @@ bool LayerAndroid::drawGL(bool layerTilesDisabled) return askScreenUpdate; } -bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas) +bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style) { bool askScreenUpdate = false; int count = this->countChildren(); @@ -856,14 +900,14 @@ bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas) std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); for (int i = 0; i < count; i++) { LayerAndroid* layer = sublayers[i]; - askScreenUpdate |= layer->drawCanvas(canvas); + askScreenUpdate |= layer->drawCanvas(canvas, true, style); } } return askScreenUpdate; } -void LayerAndroid::contentDraw(SkCanvas* canvas) +void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style) { if (m_recordingPicture) canvas->drawPicture(*m_recordingPicture); @@ -872,10 +916,17 @@ void LayerAndroid::contentDraw(SkCanvas* canvas) float w = getSize().width(); float h = getSize().height(); SkPaint paint; - paint.setARGB(128, 255, 0, 0); + + if (style == MergedLayers) + paint.setARGB(255, 255, 255, 0); + else if (style == UnmergedLayers) + paint.setARGB(255, 255, 0, 0); + else if (style == FlattenedLayers) + paint.setARGB(255, 255, 0, 255); + canvas->drawLine(0, 0, w, h, paint); canvas->drawLine(0, h, w, 0, paint); - paint.setARGB(128, 0, 255, 0); + canvas->drawLine(0, 0, 0, h, paint); canvas->drawLine(0, h, w, h, paint); canvas->drawLine(w, h, w, 0, paint); @@ -883,7 +934,8 @@ void LayerAndroid::contentDraw(SkCanvas* canvas) } } -void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, android::DrawExtra* extra) +void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, + android::DrawExtra* extra, PaintStyle style) { if (m_haveClip) { SkRect r; @@ -912,7 +964,7 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, android::DrawExtra } ImagesManager::instance()->releaseImage(m_imageCRC); } - contentDraw(canvas); + contentDraw(canvas, style); if (extra) extra->draw(canvas, this); } diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index 62fc863..4110aac 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -66,6 +66,7 @@ namespace WebCore { class AndroidAnimation; class BaseTileTexture; class GLWebViewState; +class LayerMergeState; class RenderLayer; class TiledPage; class PaintedSurface; @@ -134,8 +135,8 @@ public: float getScale() { return m_scale; } virtual bool drawGL(bool layerTilesDisabled); - virtual bool drawCanvas(SkCanvas*); - bool drawChildrenCanvas(SkCanvas*); + virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style); + bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style); void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix, const FloatRect& clip, float opacity, float scale); @@ -237,7 +238,7 @@ public: void clearDirtyRegion(); - virtual void contentDraw(SkCanvas*); + virtual void contentDraw(SkCanvas* canvas, PaintStyle style); virtual bool isMedia() const { return false; } virtual bool isVideo() const { return false; } @@ -254,8 +255,6 @@ public: friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream); friend void android::cleanupImageRefs(LayerAndroid* layer); - void obtainTextureForPainting(LayerAndroid* drawingLayer); - // Update layers using another tree. Only works for basic properties // such as the position, the transform. Return true if anything more // complex is needed. @@ -271,15 +270,17 @@ public: void copyAnimationStartTimesRecursive(LayerAndroid* oldTree); // rendering asset management - void setIsPainting(Layer* drawingTree); + SkRegion* getInvalRegion() { return &m_dirtyRegion; } void mergeInvalsInto(LayerAndroid* replacementTree); - void assignGroups(Vector<LayerGroup*>* allGroups); + bool canJoinGroup(LayerGroup* group); + void assignGroups(LayerMergeState* mergeState); LayerGroup* group() { return m_layerGroup; } -protected: - virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra); + void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; } +protected: + virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); IntPoint m_offset; IntPoint m_iframeOffset; IntPoint m_iframeScrollOffset; @@ -359,6 +360,7 @@ private: SubclassType m_subclassType; bool m_hasText; + bool m_intrinsicallyComposited; LayerGroup* m_layerGroup; diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.cpp b/Source/WebCore/platform/graphics/android/LayerGroup.cpp index cb1cf9b..6980f3e 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.cpp +++ b/Source/WebCore/platform/graphics/android/LayerGroup.cpp @@ -53,13 +53,12 @@ // LayerGroups with an area larger than 2048*2048 should never be unclipped #define MAX_UNCLIPPED_AREA 4194304 -#define TEMP_LAYER m_layers[0] - namespace WebCore { LayerGroup::LayerGroup() - : m_hasText(false) - , m_dualTiledTexture(0) + : m_dualTiledTexture(0) + , m_needsTexture(false) + , m_hasText(false) { #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerGroup"); @@ -77,61 +76,140 @@ LayerGroup::~LayerGroup() #endif } -void LayerGroup::initializeGroup(LayerAndroid* newLayer, const SkRegion& newLayerInval, - LayerAndroid* oldLayer) +bool LayerGroup::tryUpdateLayerGroup(LayerGroup* oldLayerGroup) { - if (!newLayer->needsTexture()) - return; + if (!needsTexture() || !oldLayerGroup->needsTexture()) + return false; + + // merge layer group based on first layer ID + if (getFirstLayer()->uniqueId() != oldLayerGroup->getFirstLayer()->uniqueId()) + return false; + + m_dualTiledTexture = oldLayerGroup->m_dualTiledTexture; + SkSafeRef(m_dualTiledTexture); - XLOG("init on LG %p, layer %p, oldlayer %p", this, newLayer, oldLayer); - if (oldLayer && oldLayer->group() && oldLayer->group()->m_dualTiledTexture) { - // steal DTT from old group, and apply new inval - m_dualTiledTexture = oldLayer->group()->m_dualTiledTexture; - SkSafeRef(m_dualTiledTexture); - m_dualTiledTexture->markAsDirty(newLayerInval); - } else - m_dualTiledTexture = new DualTiledTexture(); - } - -void LayerGroup::addLayer(LayerAndroid* layer) + XLOG("%p taking old DTT %p from group %p, nt %d", + this, m_dualTiledTexture, oldLayerGroup, oldLayerGroup->needsTexture()); + + if (!m_dualTiledTexture) { + // no DTT to inval, so don't worry about it. + return true; + } + + if (singleLayer() && oldLayerGroup->singleLayer()) { + // both are single matching layers, simply apply inval + SkRegion* layerInval = getFirstLayer()->getInvalRegion(); + m_dualTiledTexture->markAsDirty(*layerInval); + } else { + bool inval = false; + for (unsigned int i = 0; i < m_layers.size(); i++) { + if (m_layers[i]->uniqueId() != oldLayerGroup->m_layers[i]->uniqueId() + || !m_layers[i]->getInvalRegion()->isEmpty()) { + // layer list has changed, or one has been inval'd + inval = true; + break; + } + } + + if (inval) { + // fully invalidate the layer + // TODO: partial multi-layer invalidations + SkRegion inval; + inval.setRect(-1e8, -1e8, 2e8, 2e8); + m_dualTiledTexture->markAsDirty(inval); + } + } + return true; +} + +void LayerGroup::addLayer(LayerAndroid* layer, const TransformationMatrix& transform) { m_layers.append(layer); SkSafeRef(layer); + + m_needsTexture |= layer->needsTexture(); + m_hasText |= layer->hasText(); + + // calculate area size for comparison later + IntRect rect = layer->unclippedArea(); + SkPoint pos = layer->getPosition(); + rect.setLocation(IntPoint(pos.fX, pos.fY)); + + if (layer->needsTexture()) { + if (m_unclippedArea.isEmpty()) { + m_drawTransform = transform; + m_drawTransform.translate3d(-pos.fX, -pos.fY, 0); + m_unclippedArea = rect; + } else + m_unclippedArea.unite(rect); + XLOG("LG %p adding LA %p, size %d, %d %dx%d, now LG size %d,%d %dx%d", + this, layer, rect.x(), rect.y(), rect.width(), rect.height(), + m_unclippedArea.x(), m_unclippedArea.y(), + m_unclippedArea.width(), m_unclippedArea.height()); + } +} + +IntRect LayerGroup::visibleArea() +{ + if (singleLayer()) + return getFirstLayer()->visibleArea(); + + IntRect rect = m_unclippedArea; + + // clip with the viewport in documents coordinate + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + rect.intersect(documentViewport); + + // TODO: handle recursive layer clip + + return rect; } void LayerGroup::prepareGL(bool layerTilesDisabled) { - if (!m_dualTiledTexture) - return; + if (!m_dualTiledTexture) { + XLOG("prepareGL on LG %p, no DTT, needsTexture? %d", + this, m_dualTiledTexture, needsTexture()); + + if (needsTexture()) + m_dualTiledTexture = new DualTiledTexture(); + else + return; + } if (layerTilesDisabled) { m_dualTiledTexture->discardTextures(); } else { - XLOG("prepareGL on LG %p with DTT %p", this, m_dualTiledTexture); - bool allowZoom = m_hasText; // only allow for scale > 1 if painting vectors + bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors IntRect prepareArea = computePrepareArea(); - m_dualTiledTexture->prepareGL(TEMP_LAYER->state(), TEMP_LAYER->hasText(), + + XLOG("prepareGL on LG %p with DTT %p, %d layers", + this, m_dualTiledTexture, m_layers.size()); + m_dualTiledTexture->prepareGL(getFirstLayer()->state(), allowZoom, prepareArea, this); } } bool LayerGroup::drawGL(bool layerTilesDisabled) { - if (!TEMP_LAYER->visible()) + if (!getFirstLayer()->visible()) return false; - FloatRect drawClip = TEMP_LAYER->drawClip(); + FloatRect drawClip = getFirstLayer()->drawClip(); FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip); TilesManager::instance()->shader()->clip(clippingRect); bool askRedraw = false; if (m_dualTiledTexture && !layerTilesDisabled) { XLOG("drawGL on LG %p with DTT %p", this, m_dualTiledTexture); - IntRect visibleArea = TEMP_LAYER->visibleArea(); - const TransformationMatrix* transform = TEMP_LAYER->drawTransform(); - askRedraw |= m_dualTiledTexture->drawGL(visibleArea, opacity(), transform); + + IntRect drawArea = visibleArea(); + askRedraw |= m_dualTiledTexture->drawGL(drawArea, opacity(), drawTransform()); } - askRedraw |= TEMP_LAYER->drawGL(layerTilesDisabled); + + // draw member layers (draws image textures, glextras) + for (unsigned int i = 0; i < m_layers.size(); i++) + askRedraw |= m_layers[i]->drawGL(layerTilesDisabled); return askRedraw; } @@ -155,15 +233,16 @@ bool LayerGroup::isReady() IntRect LayerGroup::computePrepareArea() { IntRect area; - if (!TEMP_LAYER->contentIsScrollable() - && TEMP_LAYER->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { - area = TEMP_LAYER->unclippedArea(); + if (!getFirstLayer()->contentIsScrollable() + && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) { + + area = singleLayer() ? getFirstLayer()->unclippedArea() : m_unclippedArea; double total = ((double) area.width()) * ((double) area.height()); if (total > MAX_UNCLIPPED_AREA) - area = TEMP_LAYER->visibleArea(); + area = visibleArea(); } else { - area = TEMP_LAYER->visibleArea(); + area = visibleArea(); } return area; @@ -174,26 +253,48 @@ void LayerGroup::computeTexturesAmount(TexturesResult* result) if (!m_dualTiledTexture) return; - // TODO: don't calculate through layer recursion, use the group list - m_dualTiledTexture->computeTexturesAmount(result, TEMP_LAYER); + m_dualTiledTexture->computeTexturesAmount(result, getFirstLayer()); } bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) { - SkPicture *picture = TEMP_LAYER->picture(); - if (!picture) { - XLOGC("LG %p couldn't paint, no picture in layer %p", this, TEMP_LAYER); - return false; - } + if (singleLayer()) { + getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers); + } else { + SkAutoCanvasRestore acr(canvas, true); + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_drawTransform); + + SkMatrix inverse; + inverse.reset(); + matrix.invert(&inverse); - canvas->drawPicture(*picture); + SkMatrix canvasMatrix = canvas->getTotalMatrix(); + inverse.postConcat(canvasMatrix); + canvas->setMatrix(inverse); + for (unsigned int i=0; i<m_layers.size(); i++) + m_layers[i]->drawCanvas(canvas, false, Layer::MergedLayers); + } return true; } float LayerGroup::opacity() { - return TEMP_LAYER->getOpacity(); + if (singleLayer()) + return getFirstLayer()->getOpacity(); + return 1.0; +} + +const TransformationMatrix* LayerGroup::drawTransform() +{ + // single layer groups query the layer's draw transform, while multi-layer + // groups copy the draw transform once, during initialization + // TODO: support fixed multi-layer groups by querying the changing drawTransform + if (singleLayer()) + return getFirstLayer()->drawTransform(); + + return &m_drawTransform; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.h b/Source/WebCore/platform/graphics/android/LayerGroup.h index 0546139..e3e0247 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.h +++ b/Source/WebCore/platform/graphics/android/LayerGroup.h @@ -26,6 +26,7 @@ #ifndef LayerGroup_h #define LayerGroup_h +#include "IntRect.h" #include "TilePainter.h" #include "Vector.h" @@ -44,10 +45,11 @@ public: LayerGroup(); virtual ~LayerGroup(); - void initializeGroup(LayerAndroid* newLayer, const SkRegion& newLayerInval, - LayerAndroid* oldLayer); + bool tryUpdateLayerGroup(LayerGroup* oldLayerGroup); - void addLayer(LayerAndroid* layer); + + void addLayer(LayerAndroid* layer, const TransformationMatrix& transform); + IntRect visibleArea(); void prepareGL(bool layerTilesDisabled); bool drawGL(bool layerTilesDisabled); void swapTiles(); @@ -56,15 +58,48 @@ public: IntRect computePrepareArea(); void computeTexturesAmount(TexturesResult* result); + LayerAndroid* getFirstLayer() { return m_layers[0]; } + bool singleLayer() { return m_layers.size() == 1; } + bool needsTexture() { return m_needsTexture; } + bool hasText() { return m_hasText; } + // TilePainter methods virtual bool paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed); virtual float opacity(); private: - bool m_hasText; + const TransformationMatrix* drawTransform(); + IntRect m_unclippedArea; + TransformationMatrix m_drawTransform; + DualTiledTexture* m_dualTiledTexture; + bool m_needsTexture; + bool m_hasText; Vector<LayerAndroid*> m_layers; }; +class LayerMergeState { +public: + LayerMergeState(Vector<LayerGroup*>* const allGroups) + : groupList(allGroups) + , currentLayerGroup(0) + , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping + , depth(0) + {} + + // vector storing all generated layer groups + Vector<LayerGroup*>* const groupList; + + // currently merging group. if cleared, no more layers may join + LayerGroup* currentLayerGroup; + + // records depth within non-mergeable parents (clipping, fixed, scrolling) + // and disable merging therein. + int nonMergeNestedLevel; + + // counts layer tree depth for debugging + int depth; +}; + } // namespace WebCore #endif //#define LayerGroup_h diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp index 48e4f27..55fa51a 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp +++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp @@ -72,7 +72,9 @@ SurfaceCollection::SurfaceCollection(BaseLayerAndroid* baseLayer) // allocate groups for layers, merging where possible XLOG("new tree, allocating groups for tree %p", m_baseLayer); - m_compositedRoot->assignGroups(&m_layerGroups); + + LayerMergeState layerMergeState(&m_layerGroups); + m_compositedRoot->assignGroups(&layerMergeState); } #ifdef DEBUG_COUNT ClassTracker::instance()->increment("SurfaceCollection"); @@ -183,7 +185,7 @@ void SurfaceCollection::drawCanvas(SkCanvas* canvas, bool drawLayers) // draw the layers onto the same canvas (for single surface mode) if (drawLayers && m_compositedRoot) - m_compositedRoot->drawCanvas(canvas); + m_compositedRoot->drawCanvas(canvas, true, Layer::FlattenedLayers); } @@ -198,12 +200,20 @@ void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface) m_baseLayer->setIsPainting(); - LayerAndroid* oldCompositedSurface = 0; - if (drawingSurface) - oldCompositedSurface = drawingSurface->m_compositedRoot; + if (!drawingSurface) + return; - if (m_compositedRoot) - m_compositedRoot->setIsPainting(oldCompositedSurface); + for (unsigned int i = 0; i < m_layerGroups.size(); i++) { + LayerGroup* newLayerGroup = m_layerGroups[i]; + if (!newLayerGroup->needsTexture()) + continue; + + for (unsigned int j = 0; j < drawingSurface->m_layerGroups.size(); j++) { + LayerGroup* oldLayerGroup = drawingSurface->m_layerGroups[j]; + if (newLayerGroup->tryUpdateLayerGroup(oldLayerGroup)) + break; + } + } } void SurfaceCollection::setIsDrawing() diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h index 02ab8e9..5e421f0 100644 --- a/Source/WebCore/rendering/RenderLayer.h +++ b/Source/WebCore/rendering/RenderLayer.h @@ -498,6 +498,12 @@ public: bool hasOverflowScroll() const { return m_hasOverflowScroll; } bool hasOverflowParent() const; #endif +#if PLATFORM(ANDROID) + bool intrinsicallyComposited() const { return m_intrinsicallyComposited; } + void setIntrinsicallyComposited(bool intrinsicallyComposited) { + m_intrinsicallyComposited = intrinsicallyComposited; + } +#endif private: // The normal operator new is disallowed on all render objects. @@ -751,6 +757,9 @@ protected: bool m_shouldComposite : 1; #endif #endif +#if PLATFORM(ANDROID) + bool m_intrinsicallyComposited : 1; +#endif bool m_containsDirtyOverlayScrollbars : 1; #if ENABLE(ANDROID_OVERFLOW_SCROLL) diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 25a08e7..d7f5c6b 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -682,7 +682,12 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O layer->updateLayerPosition(); layer->updateZOrderLists(); layer->updateNormalFlowList(); - +#if PLATFORM(ANDROID) + RenderObject* renderer = layer->renderer(); + bool intCom = requiresCompositingLayer(layer); + layer->setIntrinsicallyComposited(intCom); +#endif + // Clear the flag layer->setHasCompositingDescendant(false); |