• 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 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 
LayerAndroid(RenderLayer * owner)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 
LayerAndroid(const LayerAndroid & layer)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 
~LayerAndroid()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 
maxZoomScale() const217 float LayerAndroid::maxZoomScale() const
218 {
219     return m_content ? m_content->maxZoomScale() : 1.0f;
220 }
221 
222 static int gDebugNbAnims = 0;
223 
evaluateAnimations()224 bool LayerAndroid::evaluateAnimations()
225 {
226     double time = WTF::currentTime();
227     gDebugNbAnims = 0;
228     return evaluateAnimations(time);
229 }
230 
hasAnimations() const231 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 
evaluateAnimations(double time)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 
initAnimations()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 
addDirtyArea()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 
addAnimation(PassRefPtr<AndroidAnimation> prpAnim)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 
removeAnimationsForProperty(AnimatedPropertyID property)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 
removeAnimationsForKeyframes(const String & name)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?
setMaskLayer(LayerAndroid * layer)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 
setBackgroundColor(SkColor color)345 void LayerAndroid::setBackgroundColor(SkColor color)
346 {
347     m_backgroundColor = color;
348 }
349 
translation() const350 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 
updatePosition(SkRect viewport,IFrameLayerAndroid * parentIframeLayer)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 
updateLayerPositions(SkRect viewport,IFrameLayerAndroid * parentIframeLayer)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 
updatePositions()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 
updateLocalTransformAndClip(const TransformationMatrix & parentMatrix,const FloatRect & clipping)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 
updateGLPositionsAndScale(const TransformationMatrix & parentMatrix,const FloatRect & clipping,float opacity,float scale,bool forceCalculation,bool disableFixedElemUpdate)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 
visible()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 
setContentsImage(SkBitmapRef * img)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 
setContent(LayerContent * content)527 void LayerAndroid::setContent(LayerContent* content)
528 {
529     SkSafeRef(content);
530     SkSafeUnref(m_content);
531     m_content = content;
532 }
533 
canUpdateWithBlit()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 
needsTexture()551 bool LayerAndroid::needsTexture()
552 {
553     return (m_content && !m_content->isEmpty())
554             || (m_originalLayer && m_originalLayer->needsTexture());
555 }
556 
clippedRect() const557 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 
nbLayers()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 
nbTexturedLayers()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 
showLayer(int indent)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 
mergeInvalsInto(LayerAndroid * replacementTree)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 
compareLayerZ(const LayerAndroid * a,const LayerAndroid * b)638 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
639 {
640     return a->zValue() > b->zValue();
641 }
642 
canJoinSurface(Surface * surface)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 
assignSurfaces(LayerMergeState * mergeState)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)
clearDirtyRegion()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 
setHwAccelerated(bool hwAccelerated)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 
fullContentAreaMapped() const755 FloatRect LayerAndroid::fullContentAreaMapped() const
756 {
757     FloatRect area(0,0, getWidth(), getHeight());
758     FloatRect globalArea = m_drawTransform.mapRect(area);
759     return globalArea;
760 }
761 
fullContentArea() const762 IntRect LayerAndroid::fullContentArea() const
763 {
764     IntRect area(0,0, getWidth(), getHeight());
765     return area;
766 }
767 
visibleContentArea(bool force3dContentVisible) const768 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 
drawCanvas(SkCanvas * canvas,bool drawChildren,PaintStyle style)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 
collect3dRenderingContext(Vector<LayerAndroid * > & layersInContext)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 
drawSurfaceAndChildrenGL()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 
drawTreeSurfacesGL()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 
drawGL(bool layerTilesDisabled)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 
drawChildrenCanvas(SkCanvas * canvas,PaintStyle style)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 
contentDraw(SkCanvas * canvas,PaintStyle style)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 
onDraw(SkCanvas * canvas,SkScalar opacity,android::DrawExtra * extra,PaintStyle style)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 
setFixedPosition(FixedPositioning * position)1005 void LayerAndroid::setFixedPosition(FixedPositioning* position) {
1006     if (m_fixedPosition && m_fixedPosition != position)
1007         delete m_fixedPosition;
1008     m_fixedPosition = position;
1009 }
1010 
dumpLayer(LayerDumper * dumper) const1011 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 
dumpLayers(LayerDumper * dumper) const1035 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 
findById(int match)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