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