summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2012-03-05 11:08:09 -0800
committerChris Craik <ccraik@google.com>2012-03-07 13:16:07 -0800
commit0de5188ef06efbbf15051a6ea07ba970253c569c (patch)
tree963f3d067f5708e1c67f30c55b96980b0e0d94b4 /Source
parent221265b7850cf40a096dd513e2a492454405a6d0 (diff)
downloadexternal_webkit-0de5188ef06efbbf15051a6ea07ba970253c569c.zip
external_webkit-0de5188ef06efbbf15051a6ea07ba970253c569c.tar.gz
external_webkit-0de5188ef06efbbf15051a6ea07ba970253c569c.tar.bz2
UI-side layer merging
Merge multiple painted layers into a LayerGroup to share a dualTiledTexture see LayerAndroid::canJoinGroup() for merging rules Change-Id: I5f5b156894c3743825f570b47d34e905d74de10a
Diffstat (limited to 'Source')
-rw-r--r--Source/WebCore/platform/graphics/android/FixedLayerAndroid.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/FixedLayerAndroid.h2
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp8
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.h3
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp162
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h20
-rw-r--r--Source/WebCore/platform/graphics/android/LayerGroup.cpp189
-rw-r--r--Source/WebCore/platform/graphics/android/LayerGroup.h43
-rw-r--r--Source/WebCore/platform/graphics/android/SurfaceCollection.cpp24
-rw-r--r--Source/WebCore/rendering/RenderLayer.h9
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp7
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);