Home | History | Annotate | Download | only in layers
      1 #define LOG_TAG "LayerAndroid"
      2 #define LOG_NDEBUG 1
      3 
      4 #include "config.h"
      5 #include "LayerAndroid.h"
      6 
      7 #if USE(ACCELERATED_COMPOSITING)
      8 
      9 #include "AndroidLog.h"
     10 #include "AndroidAnimation.h"
     11 #include "ClassTracker.h"
     12 #include "DrawExtra.h"
     13 #include "DumpLayer.h"
     14 #include "FixedPositioning.h"
     15 #include "GLUtils.h"
     16 #include "GLWebViewState.h"
     17 #include "ImagesManager.h"
     18 #include "InspectorCanvas.h"
     19 #include "LayerContent.h"
     20 #include "MediaLayer.h"
     21 #include "ParseCanvas.h"
     22 #include "PictureLayerContent.h"
     23 #include "PrerenderedInval.h"
     24 #include "SkBitmapRef.h"
     25 #include "SkDevice.h"
     26 #include "SkDrawFilter.h"
     27 #include "SkPaint.h"
     28 #include "SkPicture.h"
     29 #include "SkTypeface.h"
     30 #include "Surface.h"
     31 #include "TilesManager.h"
     32 
     33 #include <wtf/CurrentTime.h>
     34 #include <wtf/text/CString.h>
     35 #include <math.h>
     36 
     37 #define DISABLE_LAYER_MERGE
     38 #undef DISABLE_LAYER_MERGE
     39 
     40 #define LAYER_MERGING_DEBUG
     41 #undef LAYER_MERGING_DEBUG
     42 
     43 namespace WebCore {
     44 
     45 static int gUniqueId;
     46 
     47 class OpacityDrawFilter : public SkDrawFilter {
     48 public:
     49     OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
     50     virtual bool filter(SkPaint* paint, Type)
     51     {
     52         paint->setAlpha(m_opacity);
     53         return true;
     54     }
     55 private:
     56     int m_opacity;
     57 };
     58 
     59 ///////////////////////////////////////////////////////////////////////////////
     60 
     61 LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
     62     m_uniqueId(++gUniqueId),
     63     m_haveClip(false),
     64     m_backfaceVisibility(true),
     65     m_visible(true),
     66     m_backgroundColor(0),
     67     m_preserves3D(false),
     68     m_anchorPointZ(0),
     69     m_isPositionAbsolute(false),
     70     m_fixedPosition(0),
     71     m_zValue(0),
     72     m_content(0),
     73     m_imageCRC(0),
     74     m_scale(1),
     75     m_lastComputeTextureSize(0),
     76     m_owningLayer(owner),
     77     m_type(LayerAndroid::WebCoreLayer),
     78     m_intrinsicallyComposited(true),
     79     m_surface(0),
     80     m_replicatedLayer(0),
     81     m_originalLayer(0),
     82     m_maskLayer(0)
     83 {
     84     m_dirtyRegion.setEmpty();
     85 #ifdef DEBUG_COUNT
     86     ClassTracker::instance()->increment("LayerAndroid");
     87     ClassTracker::instance()->add(this);
     88 #endif
     89 }
     90 
     91 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
     92     m_uniqueId(layer.m_uniqueId),
     93     m_haveClip(layer.m_haveClip),
     94     m_backfaceVisibility(layer.m_backfaceVisibility),
     95     m_visible(layer.m_visible),
     96     m_backgroundColor(layer.m_backgroundColor),
     97     m_preserves3D(layer.m_preserves3D),
     98     m_anchorPointZ(layer.m_anchorPointZ),
     99     m_isPositionAbsolute(layer.m_isPositionAbsolute),
    100     m_fixedPosition(0),
    101     m_zValue(layer.m_zValue),
    102     m_content(layer.m_content),
    103     m_imageCRC(layer.m_imageCRC),
    104     m_scale(layer.m_scale),
    105     m_lastComputeTextureSize(0),
    106     m_owningLayer(layer.m_owningLayer),
    107     m_type(LayerAndroid::UILayer),
    108     m_intrinsicallyComposited(layer.m_intrinsicallyComposited),
    109     m_surface(0),
    110     m_replicatedLayer(0),
    111     m_originalLayer(0),
    112     m_maskLayer(0)
    113 {
    114     if (m_imageCRC)
    115         ImagesManager::instance()->retainImage(m_imageCRC);
    116 
    117     SkSafeRef(m_content);
    118 
    119     if (layer.m_fixedPosition) {
    120         m_fixedPosition = layer.m_fixedPosition->copy(this);
    121         Layer::setShouldInheritFromRootTransform(true);
    122     }
    123 
    124     m_transform = layer.m_transform;
    125     m_drawTransform = layer.m_drawTransform;
    126     m_drawTransformUnfudged = layer.m_drawTransformUnfudged;
    127     m_childrenTransform = layer.m_childrenTransform;
    128     m_dirtyRegion = layer.m_dirtyRegion;
    129 
    130     m_replicatedLayerPosition = layer.m_replicatedLayerPosition;
    131 
    132 #ifdef ABSOLUTE_POSITION
    133     // If we have absolute elements, we may need to reorder them if they
    134     // are followed by another layer that is not also absolutely positioned.
    135     // (as absolutely positioned elements are out of the normal flow)
    136     bool hasAbsoluteChildren = false;
    137     bool hasOnlyAbsoluteFollowers = true;
    138 
    139     for (int i = 0; i < layer.countChildren(); i++) {
    140         if (layer.getChild(i)->isPositionAbsolute()) {
    141             hasAbsoluteChildren = true;
    142             continue;
    143         }
    144         if (hasAbsoluteChildren
    145             && !layer.getChild(i)->isPositionAbsolute()) {
    146             hasOnlyAbsoluteFollowers = false;
    147             break;
    148         }
    149     }
    150 
    151     if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) {
    152         Vector<LayerAndroid*> normalLayers;
    153         Vector<LayerAndroid*> absoluteLayers;
    154         for (int i = 0; i < layer.countChildren(); i++) {
    155             LayerAndroid* child = layer.getChild(i);
    156             if (child->isPositionAbsolute()
    157                 || child->isPositionFixed())
    158                 absoluteLayers.append(child);
    159             else
    160                 normalLayers.append(child);
    161         }
    162         for (unsigned int i = 0; i < normalLayers.size(); i++)
    163             addChild(normalLayers[i]->copy())->unref();
    164         for (unsigned int i = 0; i < absoluteLayers.size(); i++)
    165             addChild(absoluteLayers[i]->copy())->unref();
    166     } else {
    167         for (int i = 0; i < layer.countChildren(); i++)
    168             addChild(layer.getChild(i)->copy())->unref();
    169     }
    170 #else
    171     for (int i = 0; i < layer.countChildren(); i++)
    172         addChild(layer.getChild(i)->copy())->unref();
    173 #endif
    174 
    175     KeyframesMap::const_iterator end = layer.m_animations.end();
    176     for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
    177         // Deep copy the key's string, to avoid cross-thread refptr use
    178         pair<String, int> newKey(it->first.first.threadsafeCopy(), it->first.second);
    179         m_animations.add(newKey, it->second);
    180     }
    181 
    182     if (layer.m_replicatedLayer) {
    183         // The replicated layer is always the first child
    184         m_replicatedLayer = getChild(0);
    185         m_replicatedLayer->setOriginalLayer(this);
    186     }
    187 
    188     if (layer.m_maskLayer)
    189         m_maskLayer = layer.m_maskLayer->copy();
    190 
    191 #ifdef DEBUG_COUNT
    192     ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
    193     ClassTracker::instance()->add(this);
    194 #endif
    195 }
    196 
    197 LayerAndroid::~LayerAndroid()
    198 {
    199     if (m_imageCRC)
    200         ImagesManager::instance()->releaseImage(m_imageCRC);
    201     if (m_fixedPosition)
    202         delete m_fixedPosition;
    203 
    204     SkSafeUnref(m_maskLayer);
    205     SkSafeUnref(m_content);
    206     // Don't unref m_surface, owned by BaseLayerAndroid
    207     m_animations.clear();
    208 #ifdef DEBUG_COUNT
    209     ClassTracker::instance()->remove(this);
    210     if (m_type == LayerAndroid::WebCoreLayer)
    211         ClassTracker::instance()->decrement("LayerAndroid");
    212     else if (m_type == LayerAndroid::UILayer)
    213         ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)");
    214 #endif
    215 }
    216 
    217 float LayerAndroid::maxZoomScale() const
    218 {
    219     return m_content ? m_content->maxZoomScale() : 1.0f;
    220 }
    221 
    222 static int gDebugNbAnims = 0;
    223 
    224 bool LayerAndroid::evaluateAnimations()
    225 {
    226     double time = WTF::currentTime();
    227     gDebugNbAnims = 0;
    228     return evaluateAnimations(time);
    229 }
    230 
    231 bool LayerAndroid::hasAnimations() const
    232 {
    233     for (int i = 0; i < countChildren(); i++) {
    234         if (getChild(i)->hasAnimations())
    235             return true;
    236     }
    237     return !!m_animations.size();
    238 }
    239 
    240 bool LayerAndroid::evaluateAnimations(double time)
    241 {
    242     bool hasRunningAnimations = false;
    243     for (int i = 0; i < countChildren(); i++) {
    244         if (getChild(i)->evaluateAnimations(time))
    245             hasRunningAnimations = true;
    246     }
    247 
    248     m_hasRunningAnimations = false;
    249     int nbAnims = 0;
    250     KeyframesMap::const_iterator end = m_animations.end();
    251     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
    252         gDebugNbAnims++;
    253         nbAnims++;
    254         LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
    255         m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time);
    256     }
    257 
    258     return hasRunningAnimations || m_hasRunningAnimations;
    259 }
    260 
    261 void LayerAndroid::initAnimations() {
    262     // tell auto-initializing animations to start now
    263     for (int i = 0; i < countChildren(); i++)
    264         getChild(i)->initAnimations();
    265 
    266     KeyframesMap::const_iterator localBegin = m_animations.begin();
    267     KeyframesMap::const_iterator localEnd = m_animations.end();
    268     for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt)
    269         (localIt->second)->suggestBeginTime(WTF::currentTime());
    270 }
    271 
    272 void LayerAndroid::addDirtyArea()
    273 {
    274     if (m_drawTransform.hasPerspective()) {
    275         state()->doFrameworkFullInval();
    276         return;
    277     }
    278 
    279     // TODO: rewrite this to handle partial invalidate, and to handle base
    280     // layer's large clip correctly
    281 
    282     IntSize layerSize(getSize().width(), getSize().height());
    283 
    284     FloatRect area =
    285         TilesManager::instance()->shader()->rectInViewCoord(m_drawTransform, layerSize);
    286     FloatRect clippingRect =
    287         TilesManager::instance()->shader()->rectInInvViewCoord(m_clippingRect);
    288     FloatRect clip =
    289         TilesManager::instance()->shader()->convertInvViewCoordToViewCoord(clippingRect);
    290 
    291     area.intersect(clip);
    292     IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
    293 
    294     state()->addDirtyArea(dirtyArea);
    295 
    296     for (int i = 0; i < countChildren(); i++)
    297         getChild(i)->addDirtyArea();
    298 }
    299 
    300 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
    301 {
    302     RefPtr<AndroidAnimation> anim = prpAnim;
    303     pair<String, int> key(anim->nameCopy(), anim->type());
    304     removeAnimationsForProperty(anim->type());
    305     m_animations.add(key, anim);
    306 }
    307 
    308 void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
    309 {
    310     KeyframesMap::const_iterator end = m_animations.end();
    311     Vector<pair<String, int> > toDelete;
    312     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
    313         if ((it->second)->type() == property)
    314             toDelete.append(it->first);
    315     }
    316 
    317     for (unsigned int i = 0; i < toDelete.size(); i++)
    318         m_animations.remove(toDelete[i]);
    319 }
    320 
    321 void LayerAndroid::removeAnimationsForKeyframes(const String& name)
    322 {
    323     KeyframesMap::const_iterator end = m_animations.end();
    324     Vector<pair<String, int> > toDelete;
    325     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
    326         if ((it->second)->isNamed(name))
    327             toDelete.append(it->first);
    328     }
    329 
    330     for (unsigned int i = 0; i < toDelete.size(); i++)
    331         m_animations.remove(toDelete[i]);
    332 }
    333 
    334 // We only use the bounding rect of the layer as mask...
    335 // FIXME: use a real mask?
    336 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
    337 {
    338     SkSafeRef(layer);
    339     SkSafeUnref(m_maskLayer);
    340     m_maskLayer = layer;
    341     if (layer)
    342         m_haveClip = true;
    343 }
    344 
    345 void LayerAndroid::setBackgroundColor(SkColor color)
    346 {
    347     m_backgroundColor = color;
    348 }
    349 
    350 FloatPoint LayerAndroid::translation() const
    351 {
    352     TransformationMatrix::DecomposedType tDecomp;
    353     m_transform.decompose(tDecomp);
    354     FloatPoint p(tDecomp.translateX, tDecomp.translateY);
    355     return p;
    356 }
    357 
    358 IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport,
    359                                                  IFrameLayerAndroid* parentIframeLayer)
    360 {
    361     // subclasses can implement this virtual function to modify their position
    362     if (m_fixedPosition)
    363         return m_fixedPosition->updatePosition(viewport, parentIframeLayer);
    364     return parentIframeLayer;
    365 }
    366 
    367 void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer)
    368 {
    369     ALOGV("updating fixed positions, using viewport %fx%f - %fx%f",
    370           viewport.fLeft, viewport.fTop,
    371           viewport.width(), viewport.height());
    372 
    373     IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer);
    374 
    375     int count = this->countChildren();
    376     for (int i = 0; i < count; i++)
    377         this->getChild(i)->updateLayerPositions(viewport, iframeLayer);
    378 }
    379 
    380 void LayerAndroid::updatePositions()
    381 {
    382     // apply the viewport to us
    383     if (!isPositionFixed()) {
    384         // turn our fields into a matrix.
    385         //
    386         // FIXME: this should happen in the caller, and we should remove these
    387         // fields from our subclass
    388         SkMatrix matrix;
    389         GLUtils::toSkMatrix(matrix, m_transform);
    390         this->setMatrix(matrix);
    391     }
    392 
    393     // now apply it to our children
    394     int count = this->countChildren();
    395     for (int i = 0; i < count; i++)
    396         this->getChild(i)->updatePositions();
    397 }
    398 
    399 void LayerAndroid::updateLocalTransformAndClip(const TransformationMatrix& parentMatrix,
    400                                                const FloatRect& clipping)
    401 {
    402     FloatPoint position(getPosition().x() + m_replicatedLayerPosition.x() - getScrollOffset().x(),
    403                         getPosition().y() + m_replicatedLayerPosition.y() - getScrollOffset().y());
    404 
    405     if (isPositionFixed())
    406         m_drawTransform.makeIdentity();
    407     else
    408         m_drawTransform = parentMatrix;
    409 
    410     if (m_transform.isIdentity()) {
    411         m_drawTransform.translate3d(position.x(),
    412                                     position.y(),
    413                                     0);
    414     } else {
    415         float originX = getAnchorPoint().x() * getWidth();
    416         float originY = getAnchorPoint().y() * getHeight();
    417         m_drawTransform.translate3d(originX + position.x(),
    418                                     originY + position.y(),
    419                                     anchorPointZ());
    420         m_drawTransform.multiply(m_transform);
    421         m_drawTransform.translate3d(-originX,
    422                                     -originY,
    423                                     -anchorPointZ());
    424     }
    425 
    426     m_drawTransformUnfudged = m_drawTransform;
    427     if (m_drawTransform.isIdentityOrTranslation()
    428         && surface() && surface()->allowTransformFudging()) {
    429         // adjust the translation coordinates of the draw transform matrix so
    430         // that layers (defined in content coordinates) will align to display/view pixels
    431 
    432         // the surface may not allow fudging if it uses the draw transform at paint time
    433         float desiredContentX = round(m_drawTransform.m41() * m_scale) / m_scale;
    434         float desiredContentY = round(m_drawTransform.m42() * m_scale) / m_scale;
    435         ALOGV("fudging translation from %f, %f to %f, %f",
    436               m_drawTransform.m41(), m_drawTransform.m42(),
    437               desiredContentX, desiredContentY);
    438         m_drawTransform.setM41(desiredContentX);
    439         m_drawTransform.setM42(desiredContentY);
    440     }
    441 
    442     m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform,
    443                                                           getSize().width(),
    444                                                           getSize().height());
    445 
    446     if (m_haveClip) {
    447         // The clipping rect calculation and intersetion will be done in content
    448         // coordinates.
    449         FloatRect rect(0, 0, getWidth(), getHeight());
    450         FloatRect clip = m_drawTransform.mapRect(rect);
    451         clip.intersect(clipping);
    452         setDrawClip(clip);
    453     } else {
    454         setDrawClip(clipping);
    455     }
    456     ALOGV("%s - %d %f %f %f %f",
    457           subclassType() == BaseLayer ? "BASE" : "nonbase",
    458           m_haveClip, m_clippingRect.x(), m_clippingRect.y(),
    459           m_clippingRect.width(), m_clippingRect.height());
    460 
    461     setVisible(m_backfaceVisibility || m_drawTransform.inverse().m33() >= 0);
    462 }
    463 
    464 void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
    465                                              const FloatRect& clipping, float opacity,
    466                                              float scale, bool forceCalculation,
    467                                              bool disableFixedElemUpdate)
    468 {
    469     m_scale = scale;
    470 
    471     opacity *= getOpacity();
    472     setDrawOpacity(opacity);
    473 
    474     // constantly recalculate the draw transform of layers that may require it (and their children)
    475     forceCalculation |= hasDynamicTransform();
    476 
    477     forceCalculation &= !(disableFixedElemUpdate && isPositionFixed());
    478     if (forceCalculation)
    479         updateLocalTransformAndClip(parentMatrix, clipping);
    480 
    481     if (!countChildren() || !m_visible)
    482         return;
    483 
    484     TransformationMatrix childMatrix = m_drawTransformUnfudged;
    485     // Flatten to 2D if the layer doesn't preserve 3D.
    486     if (!preserves3D()) {
    487         childMatrix.setM13(0);
    488         childMatrix.setM23(0);
    489         childMatrix.setM31(0);
    490         childMatrix.setM32(0);
    491         childMatrix.setM33(1);
    492         childMatrix.setM34(0);
    493         childMatrix.setM43(0);
    494     }
    495 
    496     // now apply it to our children
    497     childMatrix.translate3d(getScrollOffset().x(), getScrollOffset().y(), 0);
    498     if (!m_childrenTransform.isIdentity()) {
    499         childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
    500         childMatrix.multiply(m_childrenTransform);
    501         childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
    502     }
    503     for (int i = 0; i < countChildren(); i++)
    504         this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(),
    505                                                      opacity, scale, forceCalculation,
    506                                                      disableFixedElemUpdate);
    507 }
    508 
    509 bool LayerAndroid::visible() {
    510     // TODO: avoid climbing tree each access
    511     LayerAndroid* current = this;
    512     while (current->getParent()) {
    513         if (!current->m_visible)
    514             return false;
    515         current = static_cast<LayerAndroid*>(current->getParent());
    516     }
    517     return true;
    518 }
    519 
    520 void LayerAndroid::setContentsImage(SkBitmapRef* img)
    521 {
    522     ImageTexture* image = ImagesManager::instance()->setImage(img);
    523     ImagesManager::instance()->releaseImage(m_imageCRC);
    524     m_imageCRC = image ? image->imageCRC() : 0;
    525 }
    526 
    527 void LayerAndroid::setContent(LayerContent* content)
    528 {
    529     SkSafeRef(content);
    530     SkSafeUnref(m_content);
    531     m_content = content;
    532 }
    533 
    534 bool LayerAndroid::canUpdateWithBlit()
    535 {
    536     if (!m_content || !m_scale)
    537         return false;
    538     IntRect clip = clippedRect();
    539     IntRect dirty = m_dirtyRegion.getBounds();
    540     dirty.intersect(clip);
    541     PrerenderedInval* prerendered = m_content->prerenderForRect(dirty);
    542     if (!prerendered)
    543         return false;
    544     // Check that the scales are "close enough" to produce the same rects
    545     FloatRect screenArea = prerendered->screenArea;
    546     screenArea.scale(1 / m_scale);
    547     IntRect enclosingDocArea = enclosingIntRect(screenArea);
    548     return enclosingDocArea == prerendered->area;
    549 }
    550 
    551 bool LayerAndroid::needsTexture()
    552 {
    553     return (m_content && !m_content->isEmpty())
    554             || (m_originalLayer && m_originalLayer->needsTexture());
    555 }
    556 
    557 IntRect LayerAndroid::clippedRect() const
    558 {
    559     IntRect r(0, 0, getWidth(), getHeight());
    560     IntRect tr = m_drawTransform.mapRect(r);
    561     IntRect cr = TilesManager::instance()->shader()->clippedRectWithVisibleContentRect(tr);
    562     IntRect rect = m_drawTransform.inverse().mapRect(cr);
    563     return rect;
    564 }
    565 
    566 int LayerAndroid::nbLayers()
    567 {
    568     int nb = 0;
    569     int count = this->countChildren();
    570     for (int i = 0; i < count; i++)
    571         nb += this->getChild(i)->nbLayers();
    572     return nb+1;
    573 }
    574 
    575 int LayerAndroid::nbTexturedLayers()
    576 {
    577     int nb = 0;
    578     int count = this->countChildren();
    579     for (int i = 0; i < count; i++)
    580         nb += this->getChild(i)->nbTexturedLayers();
    581     if (needsTexture())
    582         nb++;
    583     return nb;
    584 }
    585 
    586 void LayerAndroid::showLayer(int indent)
    587 {
    588     char spaces[256];
    589     memset(spaces, 0, 256);
    590     for (int i = 0; i < indent; i++)
    591         spaces[i] = ' ';
    592 
    593     if (!indent) {
    594         ALOGD("\n\n--- LAYERS TREE ---");
    595         IntRect contentViewport(TilesManager::instance()->shader()->contentViewport());
    596         ALOGD("contentViewport(%d, %d, %d, %d)",
    597               contentViewport.x(), contentViewport.y(),
    598               contentViewport.width(), contentViewport.height());
    599     }
    600 
    601     IntRect r(0, 0, getWidth(), getHeight());
    602     IntRect tr = m_drawTransform.mapRect(r);
    603     IntRect visible = visibleContentArea();
    604     IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
    605                  m_clippingRect.width(), m_clippingRect.height());
    606     ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
    607           "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d",
    608           spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName(),
    609           subclassType(), uniqueId(), this, m_owningLayer,
    610           needsTexture() ? "needsTexture" : "",
    611           m_imageCRC ? "hasImage" : "",
    612           tr.x(), tr.y(), tr.width(), tr.height(),
    613           visible.x(), visible.y(), visible.width(), visible.height(),
    614           clip.x(), clip.y(), clip.width(), clip.height(),
    615           contentIsScrollable() ? "SCROLLABLE" : "",
    616           isPositionFixed() ? "FIXED" : "",
    617           m_content,
    618           m_content ? m_content->width() : -1,
    619           m_content ? m_content->height() : -1,
    620           m_originalLayer, m_originalLayer ? m_originalLayer->uniqueId() : -1);
    621 
    622     int count = this->countChildren();
    623     for (int i = 0; i < count; i++)
    624         this->getChild(i)->showLayer(indent + 2);
    625 }
    626 
    627 void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree)
    628 {
    629     int count = this->countChildren();
    630     for (int i = 0; i < count; i++)
    631         this->getChild(i)->mergeInvalsInto(replacementTree);
    632 
    633     LayerAndroid* replacementLayer = replacementTree->findById(uniqueId());
    634     if (replacementLayer)
    635         replacementLayer->markAsDirty(m_dirtyRegion);
    636 }
    637 
    638 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
    639 {
    640     return a->zValue() > b->zValue();
    641 }
    642 
    643 bool LayerAndroid::canJoinSurface(Surface* surface)
    644 {
    645 #ifdef DISABLE_LAYER_MERGE
    646     return false;
    647 #else
    648     // returns true if the layer can be merged onto the surface (group of layers)
    649     if (!surface)
    650         return false;
    651 
    652     LayerAndroid* lastLayer = surface->getFirstLayer();
    653 
    654     // isolate intrinsically composited layers
    655     if (needsIsolatedSurface() || lastLayer->needsIsolatedSurface())
    656         return false;
    657 
    658     // TODO: investigate potential for combining transformed layers
    659     if (!m_drawTransform.isIdentityOrTranslation()
    660         || !lastLayer->m_drawTransform.isIdentityOrTranslation())
    661         return false;
    662 
    663     // TODO: compare other layer properties - fixed? overscroll? transformed?
    664     return true;
    665 #endif
    666 }
    667 
    668 void LayerAndroid::assignSurfaces(LayerMergeState* mergeState)
    669 {
    670     // recurse through layers in draw order, and merge layers when able
    671 
    672     bool needNewSurface = !mergeState->currentSurface
    673         || mergeState->nonMergeNestedLevel > 0
    674         || !canJoinSurface(mergeState->currentSurface);
    675 
    676     if (needNewSurface) {
    677         mergeState->currentSurface = new Surface();
    678         mergeState->surfaceList->append(mergeState->currentSurface);
    679     }
    680 
    681 #ifdef LAYER_MERGING_DEBUG
    682     ALOGD("%*slayer %p(%d) rl %p %s surface %p lvl: %d, fixed %d, anim %d, intCom %d, haveClip %d scroll %d hasText (layer: %d surface: %d) hasContent %d size %.2f x %.2f",
    683           4*mergeState->depth, "", this, m_uniqueId, m_owningLayer,
    684           needNewSurface ? "NEW" : "joins", mergeState->currentSurface,
    685           mergeState->nonMergeNestedLevel,
    686           isPositionFixed(), m_animations.size() != 0,
    687           m_intrinsicallyComposited,
    688           m_haveClip,
    689           contentIsScrollable(), m_content ? m_content->hasText() : -1,
    690           mergeState->currentSurface ? mergeState->currentSurface->hasText() : -1,
    691           needsTexture(), getWidth(), getHeight());
    692 #endif
    693 
    694     mergeState->currentSurface->addLayer(this, m_drawTransform);
    695     m_surface = mergeState->currentSurface;
    696 
    697     if (hasDynamicTransform()) {
    698         // disable layer merging within the children of these layer types
    699         mergeState->nonMergeNestedLevel++;
    700     }
    701 
    702     // pass the surface through children in drawing order, so that they may
    703     // attach themselves (and paint on it) if possible, or ignore it and create
    704     // a new one if not
    705     int count = this->countChildren();
    706     if (count > 0) {
    707         mergeState->depth++;
    708         Vector <LayerAndroid*> sublayers;
    709         for (int i = 0; i < count; i++)
    710             sublayers.append(getChild(i));
    711 
    712         // sort for the transparency
    713         std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
    714         for (int i = 0; i < count; i++)
    715             sublayers[i]->assignSurfaces(mergeState);
    716         mergeState->depth--;
    717     }
    718 
    719     if (hasDynamicTransform()) {
    720         // re-enable joining
    721         mergeState->nonMergeNestedLevel--;
    722 
    723         // disallow layers painting after to join with this surface
    724         mergeState->currentSurface = 0;
    725     }
    726 
    727     if (needsIsolatedSurface())
    728         mergeState->currentSurface = 0;
    729 
    730 }
    731 
    732 // We call this in WebViewCore, when copying the tree of layers.
    733 // As we construct a new tree that will be passed on the UI,
    734 // we mark the webkit-side tree as having no more dirty region
    735 // (otherwise we would continuously have those dirty region UI-side)
    736 void LayerAndroid::clearDirtyRegion()
    737 {
    738     int count = this->countChildren();
    739     for (int i = 0; i < count; i++)
    740         this->getChild(i)->clearDirtyRegion();
    741 
    742     m_dirtyRegion.setEmpty();
    743 }
    744 
    745 int LayerAndroid::setHwAccelerated(bool hwAccelerated)
    746 {
    747     int flags = InvalidateNone;
    748     int count = this->countChildren();
    749     for (int i = 0; i < count; i++)
    750         flags |= this->getChild(i)->setHwAccelerated(hwAccelerated);
    751 
    752     return flags | onSetHwAccelerated(hwAccelerated);
    753 }
    754 
    755 FloatRect LayerAndroid::fullContentAreaMapped() const
    756 {
    757     FloatRect area(0,0, getWidth(), getHeight());
    758     FloatRect globalArea = m_drawTransform.mapRect(area);
    759     return globalArea;
    760 }
    761 
    762 IntRect LayerAndroid::fullContentArea() const
    763 {
    764     IntRect area(0,0, getWidth(), getHeight());
    765     return area;
    766 }
    767 
    768 IntRect LayerAndroid::visibleContentArea(bool force3dContentVisible) const
    769 {
    770     IntRect area = fullContentArea();
    771     if (subclassType() == LayerAndroid::FixedBackgroundImageLayer)
    772        return area;
    773 
    774     // If transform isn't limited to 2D space, return the entire content area.
    775     // Transforming from layers to content coordinates and back doesn't
    776     // preserve 3D.
    777     if (force3dContentVisible && GLUtils::has3dTransform(m_drawTransform))
    778             return area;
    779 
    780     // First, we get the transformed area of the layer,
    781     // in content coordinates
    782     IntRect rect = m_drawTransform.mapRect(area);
    783 
    784     // Then we apply the clipping
    785     IntRect clip(m_clippingRect);
    786     rect.intersect(clip);
    787 
    788     // Now clip with the viewport in content coordinate
    789     IntRect contentViewport(TilesManager::instance()->shader()->contentViewport());
    790     rect.intersect(contentViewport);
    791 
    792     // Finally, let's return the visible area, in layers coordinate
    793     return m_drawTransform.inverse().mapRect(rect);
    794 }
    795 
    796 bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style)
    797 {
    798     if (!m_visible)
    799         return false;
    800 
    801     bool askScreenUpdate = false;
    802 
    803     {
    804         SkAutoCanvasRestore acr(canvas, true);
    805         SkRect r;
    806         r.set(m_clippingRect.x(), m_clippingRect.y(),
    807               m_clippingRect.x() + m_clippingRect.width(),
    808               m_clippingRect.y() + m_clippingRect.height());
    809         if (canvas->clipRect(r)) {
    810             SkMatrix matrix;
    811             GLUtils::toSkMatrix(matrix, m_drawTransform);
    812             SkMatrix canvasMatrix = canvas->getTotalMatrix();
    813             matrix.postConcat(canvasMatrix);
    814             canvas->setMatrix(matrix);
    815             onDraw(canvas, m_drawOpacity, 0, style);
    816         }
    817     }
    818 
    819     if (!drawChildren)
    820         return false;
    821 
    822     // When the layer is dirty, the UI thread should be notified to redraw.
    823     askScreenUpdate |= drawChildrenCanvas(canvas, style);
    824     return askScreenUpdate;
    825 }
    826 
    827 void LayerAndroid::collect3dRenderingContext(Vector<LayerAndroid*>& layersInContext)
    828 {
    829     layersInContext.append(this);
    830     if (preserves3D()) {
    831         int count = countChildren();
    832         for (int i = 0; i < count; i++)
    833             getChild(i)->collect3dRenderingContext(layersInContext);
    834     }
    835 }
    836 
    837 bool LayerAndroid::drawSurfaceAndChildrenGL()
    838 {
    839     bool askScreenUpdate = false;
    840     if (surface()->getFirstLayer() == this)
    841         askScreenUpdate |= surface()->drawGL(false);
    842 
    843     // return early, since children will be painted directly by drawTreeSurfacesGL
    844     if (preserves3D())
    845         return askScreenUpdate;
    846 
    847     int count = countChildren();
    848     Vector <LayerAndroid*> sublayers;
    849     for (int i = 0; i < count; i++)
    850         sublayers.append(getChild(i));
    851 
    852     std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
    853     for (int i = 0; i < count; i++)
    854         askScreenUpdate |= sublayers[i]->drawTreeSurfacesGL();
    855 
    856     return askScreenUpdate;
    857 }
    858 
    859 bool LayerAndroid::drawTreeSurfacesGL()
    860 {
    861     bool askScreenUpdate = false;
    862     if (preserves3D()) {
    863         // hit a preserve-3d layer, so render the entire 3D rendering context in z order
    864         Vector<LayerAndroid*> contextLayers;
    865         collect3dRenderingContext(contextLayers);
    866         std::stable_sort(contextLayers.begin(), contextLayers.end(), compareLayerZ);
    867 
    868         for (unsigned int i = 0; i < contextLayers.size(); i++)
    869             askScreenUpdate |= contextLayers[i]->drawSurfaceAndChildrenGL();
    870     } else
    871         askScreenUpdate |= drawSurfaceAndChildrenGL();
    872 
    873     return askScreenUpdate;
    874 }
    875 
    876 bool LayerAndroid::drawGL(bool layerTilesDisabled)
    877 {
    878     if (!layerTilesDisabled && m_imageCRC) {
    879         ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
    880         if (imageTexture)
    881             imageTexture->drawGL(this, getOpacity());
    882         ImagesManager::instance()->releaseImage(m_imageCRC);
    883     }
    884 
    885     state()->glExtras()->drawGL(this);
    886     bool askScreenUpdate = false;
    887 
    888     if (m_hasRunningAnimations)
    889         askScreenUpdate = true;
    890 
    891     return askScreenUpdate;
    892 }
    893 
    894 bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style)
    895 {
    896     bool askScreenUpdate = false;
    897     int count = this->countChildren();
    898     if (count > 0) {
    899         Vector <LayerAndroid*> sublayers;
    900         for (int i = 0; i < count; i++)
    901             sublayers.append(this->getChild(i));
    902 
    903         // now we sort for the transparency
    904         std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
    905         for (int i = 0; i < count; i++) {
    906             LayerAndroid* layer = sublayers[i];
    907             askScreenUpdate |= layer->drawCanvas(canvas, true, style);
    908         }
    909     }
    910 
    911     return askScreenUpdate;
    912 }
    913 
    914 void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style)
    915 {
    916     if (m_maskLayer && m_maskLayer->m_content) {
    917         // TODO: we should use a shader instead of doing
    918         // the masking in software
    919 
    920         if (m_originalLayer)
    921             m_originalLayer->m_content->draw(canvas);
    922         else if (m_content)
    923             m_content->draw(canvas);
    924 
    925         SkPaint maskPaint;
    926         maskPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
    927         int count = canvas->saveLayer(0, &maskPaint, SkCanvas::kHasAlphaLayer_SaveFlag);
    928         m_maskLayer->m_content->draw(canvas);
    929         canvas->restoreToCount(count);
    930 
    931     } else if (m_content)
    932         m_content->draw(canvas);
    933 
    934     if (TilesManager::instance()->getShowVisualIndicator()) {
    935         float w = getSize().width();
    936         float h = getSize().height();
    937         SkPaint paint;
    938 
    939         if (style == MergedLayers)
    940             paint.setARGB(255, 255, 255, 0);
    941         else if (style == UnmergedLayers)
    942             paint.setARGB(255, 255, 0, 0);
    943         else if (style == FlattenedLayers)
    944             paint.setARGB(255, 255, 0, 255);
    945 
    946         canvas->drawLine(0, 0, w, h, paint);
    947         canvas->drawLine(0, h, w, 0, paint);
    948 
    949         canvas->drawLine(0, 0, 0, h-1, paint);
    950         canvas->drawLine(0, h-1, w-1, h-1, paint);
    951         canvas->drawLine(w-1, h-1, w-1, 0, paint);
    952         canvas->drawLine(w-1, 0, 0, 0, paint);
    953 
    954         static SkTypeface* s_typeface = 0;
    955         if (!s_typeface)
    956             s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold);
    957         paint.setARGB(255, 0, 0, 255);
    958         paint.setTextSize(17);
    959         char str[256];
    960         snprintf(str, 256, "%d", uniqueId());
    961         paint.setTypeface(s_typeface);
    962         canvas->drawText(str, strlen(str), 2, h - 2, paint);
    963     }
    964 
    965     if (m_fixedPosition)
    966         return m_fixedPosition->contentDraw(canvas, style);
    967 }
    968 
    969 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity,
    970                           android::DrawExtra* extra, PaintStyle style)
    971 {
    972     if (m_haveClip) {
    973         SkRect r;
    974         r.set(0, 0, getSize().width(), getSize().height());
    975         canvas->clipRect(r);
    976         return;
    977     }
    978 
    979     // only continue drawing if layer is drawable
    980     if (!m_content && !m_imageCRC)
    981         return;
    982 
    983     // we just have this save/restore for opacity...
    984     SkAutoCanvasRestore restore(canvas, true);
    985 
    986     int canvasOpacity = SkScalarRound(opacity * 255);
    987     if (canvasOpacity < 255)
    988         canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
    989 
    990     if (m_imageCRC) {
    991         ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
    992         m_dirtyRegion.setEmpty();
    993         if (imageTexture) {
    994             SkRect dest;
    995             dest.set(0, 0, getSize().width(), getSize().height());
    996             imageTexture->drawCanvas(canvas, dest);
    997         }
    998         ImagesManager::instance()->releaseImage(m_imageCRC);
    999     }
   1000     contentDraw(canvas, style);
   1001     if (extra)
   1002         extra->draw(canvas, this);
   1003 }
   1004 
   1005 void LayerAndroid::setFixedPosition(FixedPositioning* position) {
   1006     if (m_fixedPosition && m_fixedPosition != position)
   1007         delete m_fixedPosition;
   1008     m_fixedPosition = position;
   1009 }
   1010 
   1011 void LayerAndroid::dumpLayer(LayerDumper* dumper) const
   1012 {
   1013     dumper->writeIntVal("layerId", m_uniqueId);
   1014     dumper->writeIntVal("haveClip", m_haveClip);
   1015     dumper->writeIntVal("isFixed", isPositionFixed());
   1016 
   1017     dumper->writeFloatVal("opacity", getOpacity());
   1018     dumper->writeSize("size", getSize());
   1019     dumper->writePoint("position", getPosition());
   1020     dumper->writePoint("anchor", getAnchorPoint());
   1021 
   1022     dumper->writeMatrix("drawMatrix", m_drawTransform);
   1023     dumper->writeMatrix("transformMatrix", m_transform);
   1024     dumper->writeRect("clippingRect", SkRect(m_clippingRect));
   1025 
   1026     if (m_content) {
   1027         dumper->writeIntVal("m_content.width", m_content->width());
   1028         dumper->writeIntVal("m_content.height", m_content->height());
   1029     }
   1030 
   1031     if (m_fixedPosition)
   1032         m_fixedPosition->dumpLayer(dumper);
   1033 }
   1034 
   1035 void LayerAndroid::dumpLayers(LayerDumper* dumper) const
   1036 {
   1037     dumper->beginLayer(subclassName(), this);
   1038     dumpLayer(dumper);
   1039 
   1040     dumper->beginChildren(countChildren());
   1041     if (countChildren()) {
   1042         for (int i = 0; i < countChildren(); i++)
   1043             getChild(i)->dumpLayers(dumper);
   1044     }
   1045     dumper->endChildren();
   1046     dumper->endLayer();
   1047 }
   1048 
   1049 LayerAndroid* LayerAndroid::findById(int match)
   1050 {
   1051     if (m_uniqueId == match)
   1052         return this;
   1053     for (int i = 0; i < countChildren(); i++) {
   1054         LayerAndroid* result = getChild(i)->findById(match);
   1055         if (result)
   1056             return result;
   1057     }
   1058     return 0;
   1059 }
   1060 
   1061 } // namespace WebCore
   1062 
   1063 #endif // USE(ACCELERATED_COMPOSITING)
   1064