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