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