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