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