2 #include "LayerAndroid.h"
4 #if USE(ACCELERATED_COMPOSITING)
6 #include "AndroidAnimation.h"
7 #include "ClassTracker.h"
10 #include "ImagesManager.h"
11 #include "MediaLayer.h"
12 #include "PaintedSurface.h"
13 #include "ParseCanvas.h"
14 #include "SkBitmapRef.h"
15 #include "SkBounder.h"
16 #include "SkDrawFilter.h"
18 #include "SkPicture.h"
19 #include "TilesManager.h"
21 #include <wtf/CurrentTime.h>
24 #define LAYER_DEBUG // Add diagonals for debugging
27 #include <cutils/log.h>
28 #include <wtf/text/CString.h>
29 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
34 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
47 class OpacityDrawFilter : public SkDrawFilter {
49 OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
50 virtual void filter(SkPaint* paint, Type)
52 paint->setAlpha(m_opacity);
58 class HasTextBounder : public SkBounder {
59 virtual bool onIRect(const SkIRect& rect)
65 class HasTextCanvas : public SkCanvas {
67 HasTextCanvas(SkBounder* bounder, SkPicture* picture)
77 m_picture->abortPlayback();
85 virtual bool clipPath(const SkPath&, SkRegion::Op) {
89 virtual void commonDrawBitmap(const SkBitmap& bitmap,
94 virtual void drawPaint(const SkPaint& paint) {}
95 virtual void drawPath(const SkPath&, const SkPaint& paint) {}
96 virtual void drawPoints(PointMode, size_t,
97 const SkPoint [], const SkPaint& paint) {}
99 virtual void drawRect(const SkRect& , const SkPaint& paint) {}
100 virtual void drawSprite(const SkBitmap& , int , int ,
101 const SkPaint* paint = NULL) {}
103 virtual void drawText(const void*, size_t byteLength, SkScalar,
104 SkScalar, const SkPaint& paint)
109 virtual void drawPosText(const void* , size_t byteLength,
110 const SkPoint [], const SkPaint& paint)
115 virtual void drawPosTextH(const void*, size_t byteLength,
116 const SkScalar [], SkScalar,
117 const SkPaint& paint)
122 virtual void drawTextOnPath(const void*, size_t byteLength,
123 const SkPath&, const SkMatrix*,
124 const SkPaint& paint)
129 virtual void drawPicture(SkPicture& picture) {
130 SkCanvas::drawPicture(picture);
135 SkPicture* m_picture;
139 ///////////////////////////////////////////////////////////////////////////////
141 LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
145 m_backfaceVisibility(true),
147 m_preserves3D(false),
149 m_recordingPicture(0),
150 m_uniqueId(++gUniqueId),
156 m_lastComputeTextureSize(0),
157 m_owningLayer(owner),
158 m_type(LayerAndroid::WebCoreLayer),
161 m_backgroundColor = 0;
163 m_preserves3D = false;
164 m_iframeOffset.set(0,0);
165 m_dirtyRegion.setEmpty();
167 ClassTracker::instance()->increment("LayerAndroid");
168 ClassTracker::instance()->add(this);
172 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
173 m_haveClip(layer.m_haveClip),
174 m_isIframe(layer.m_isIframe),
175 m_uniqueId(layer.m_uniqueId),
178 m_owningLayer(layer.m_owningLayer),
179 m_type(LayerAndroid::UILayer),
182 m_isFixed = layer.m_isFixed;
183 m_imageRef = layer.m_imageRef;
185 ImagesManager::instance()->addImage(m_imageRef);
186 m_renderLayerPos = layer.m_renderLayerPos;
187 m_transform = layer.m_transform;
188 m_backfaceVisibility = layer.m_backfaceVisibility;
189 m_visible = layer.m_visible;
190 m_backgroundColor = layer.m_backgroundColor;
192 m_fixedLeft = layer.m_fixedLeft;
193 m_fixedTop = layer.m_fixedTop;
194 m_fixedRight = layer.m_fixedRight;
195 m_fixedBottom = layer.m_fixedBottom;
196 m_fixedMarginLeft = layer.m_fixedMarginLeft;
197 m_fixedMarginTop = layer.m_fixedMarginTop;
198 m_fixedMarginRight = layer.m_fixedMarginRight;
199 m_fixedMarginBottom = layer.m_fixedMarginBottom;
200 m_fixedRect = layer.m_fixedRect;
201 m_iframeOffset = layer.m_iframeOffset;
202 m_recordingPicture = layer.m_recordingPicture;
203 SkSafeRef(m_recordingPicture);
205 m_preserves3D = layer.m_preserves3D;
206 m_anchorPointZ = layer.m_anchorPointZ;
207 m_drawTransform = layer.m_drawTransform;
208 m_childrenTransform = layer.m_childrenTransform;
209 m_pictureUsed = layer.m_pictureUsed;
210 m_dirtyRegion = layer.m_dirtyRegion;
211 m_scale = layer.m_scale;
212 m_lastComputeTextureSize = 0;
214 for (int i = 0; i < layer.countChildren(); i++)
215 addChild(layer.getChild(i)->copy())->unref();
217 KeyframesMap::const_iterator end = layer.m_animations.end();
218 for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
219 pair<String, int> key((it->second)->name(), (it->second)->type());
220 m_animations.add(key, (it->second)->copy());
223 m_hasText = layer.m_hasText;
226 ClassTracker::instance()->increment("LayerAndroid - recopy (UI?)");
227 ClassTracker::instance()->add(this);
231 void LayerAndroid::checkTextPresence()
233 if (m_recordingPicture) {
234 // Let's check if we have text or not. If we don't, we can limit
235 // ourselves to scale 1!
236 HasTextBounder hasTextBounder;
237 HasTextCanvas checker(&hasTextBounder, m_recordingPicture);
239 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
240 m_recordingPicture->width(),
241 m_recordingPicture->height());
242 checker.setBitmapDevice(bitmap);
243 checker.drawPicture(*m_recordingPicture);
244 m_hasText = checker.hasText();
248 LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
252 m_recordingPicture(picture),
253 m_uniqueId(++gUniqueId),
258 m_lastComputeTextureSize(0),
260 m_type(LayerAndroid::NavCacheLayer),
263 m_backgroundColor = 0;
264 SkSafeRef(m_recordingPicture);
265 m_iframeOffset.set(0,0);
266 m_dirtyRegion.setEmpty();
268 ClassTracker::instance()->increment("LayerAndroid - from picture");
269 ClassTracker::instance()->add(this);
273 LayerAndroid::~LayerAndroid()
276 ImagesManager::instance()->removeImage(m_imageTexture->imageRef());
277 SkSafeUnref(m_recordingPicture);
278 m_animations.clear();
280 ClassTracker::instance()->remove(this);
281 if (m_type == LayerAndroid::WebCoreLayer)
282 ClassTracker::instance()->decrement("LayerAndroid");
283 else if (m_type == LayerAndroid::UILayer)
284 ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)");
285 else if (m_type == LayerAndroid::NavCacheLayer)
286 ClassTracker::instance()->decrement("LayerAndroid - from picture");
290 static int gDebugNbAnims = 0;
292 bool LayerAndroid::evaluateAnimations()
294 double time = WTF::currentTime();
296 return evaluateAnimations(time);
299 bool LayerAndroid::hasAnimations() const
301 for (int i = 0; i < countChildren(); i++) {
302 if (getChild(i)->hasAnimations())
305 return !!m_animations.size();
308 bool LayerAndroid::evaluateAnimations(double time)
310 bool hasRunningAnimations = false;
311 for (int i = 0; i < countChildren(); i++) {
312 if (getChild(i)->evaluateAnimations(time))
313 hasRunningAnimations = true;
316 m_hasRunningAnimations = false;
318 KeyframesMap::const_iterator end = m_animations.end();
319 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
322 LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
323 m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time);
326 return hasRunningAnimations || m_hasRunningAnimations;
329 void LayerAndroid::addDirtyArea()
331 IntSize layerSize(getSize().width(), getSize().height());
333 FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize);
334 FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
335 FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect);
337 area.intersect(clip);
338 IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
339 m_state->addDirtyArea(dirtyArea);
342 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
344 RefPtr<AndroidAnimation> anim = prpAnim;
345 pair<String, int> key(anim->name(), anim->type());
346 removeAnimationsForProperty(anim->type());
347 m_animations.add(key, anim);
350 void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
352 KeyframesMap::const_iterator end = m_animations.end();
353 Vector<pair<String, int> > toDelete;
354 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
355 if ((it->second)->type() == property)
356 toDelete.append(it->first);
359 for (unsigned int i = 0; i < toDelete.size(); i++)
360 m_animations.remove(toDelete[i]);
363 void LayerAndroid::removeAnimationsForKeyframes(const String& name)
365 KeyframesMap::const_iterator end = m_animations.end();
366 Vector<pair<String, int> > toDelete;
367 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
368 if ((it->second)->name() == name)
369 toDelete.append(it->first);
372 for (unsigned int i = 0; i < toDelete.size(); i++)
373 m_animations.remove(toDelete[i]);
376 // We only use the bounding rect of the layer as mask...
377 // FIXME: use a real mask?
378 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
384 void LayerAndroid::setBackgroundColor(SkColor color)
386 m_backgroundColor = color;
389 static int gDebugChildLevel;
391 FloatPoint LayerAndroid::translation() const
393 TransformationMatrix::DecomposedType tDecomp;
394 m_transform.decompose(tDecomp);
395 FloatPoint p(tDecomp.translateX, tDecomp.translateY);
399 SkRect LayerAndroid::bounds() const
406 void LayerAndroid::bounds(SkRect* rect) const
408 const SkPoint& pos = this->getPosition();
409 const SkSize& size = this->getSize();
411 // The returned rect has the translation applied
412 // FIXME: apply the full transform to the rect,
413 // and fix the text selection accordingly
414 FloatPoint p(pos.fX, pos.fY);
415 p = m_transform.mapPoint(p);
418 rect->fRight = p.x() + size.width();
419 rect->fBottom = p.y() + size.height();
422 static bool boundsIsUnique(const SkTDArray<SkRect>& region,
425 for (int i = 0; i < region.count(); i++) {
426 if (region[i].contains(local))
432 void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const
435 local.set(0, 0, std::numeric_limits<float>::max(),
436 std::numeric_limits<float>::max());
437 clipInner(region, local);
440 void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
441 const SkRect& local) const
444 bounds(&localBounds);
445 localBounds.intersect(local);
446 if (localBounds.isEmpty())
448 if (m_recordingPicture && boundsIsUnique(*region, localBounds))
449 *region->append() = localBounds;
450 for (int i = 0; i < countChildren(); i++)
451 getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
454 class FindCheck : public SkBounder {
462 bool drew() const { return m_drew; }
463 bool drewText() const { return m_drewText; }
464 void reset() { m_drew = m_drewText = false; }
467 virtual bool onIRect(const SkIRect& )
473 virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& )
475 m_drew = m_drewText = true;
483 class FindCanvas : public ParseCanvas {
485 void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY)
488 translate(-offsetX, -offsetY);
494 class LayerAndroid::FindState {
496 static const int TOUCH_SLOP = 10;
498 FindState(int x, int y)
505 m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2,
507 m_checker.setBounder(&m_findCheck);
508 m_checker.setBitmapDevice(m_bitmap);
511 const LayerAndroid* best() const { return m_best; }
512 int bestX() const { return m_bestX; }
513 int bestY() const { return m_bestY; }
515 bool drew(SkPicture* picture, const SkRect& localBounds)
518 SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft;
519 SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop;
520 m_checker.draw(picture, localX, localY);
521 return m_findCheck.drew();
524 bool drewText() { return m_findCheck.drewText(); }
526 void setBest(const LayerAndroid* best, int x, int y)
532 int x() const { return m_x; }
533 int y() const { return m_y; }
535 void setLocation(int x, int y)
546 const LayerAndroid* m_best;
547 FindCheck m_findCheck;
549 FindCanvas m_checker;
552 void LayerAndroid::findInner(LayerAndroid::FindState& state) const
557 bounds(&localBounds);
558 if (!localBounds.contains(x, y))
560 // Move into local coordinates.
561 state.setLocation(x - localBounds.fLeft, y - localBounds.fTop);
562 for (int i = 0; i < countChildren(); i++)
563 getChild(i)->findInner(state);
564 // Move back into the parent coordinates.
565 int testX = state.x();
566 int testY = state.y();
567 state.setLocation(x + localBounds.fLeft, y + localBounds.fTop);
568 if (!m_recordingPicture)
570 if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds))
572 state.setBest(this, testX, testY); // set last match (presumably on top)
575 const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const
577 FindState state(*xPtr, *yPtr);
579 rootBounds.setEmpty();
580 if (root && state.drew(root, rootBounds) && state.drewText())
581 return 0; // use the root picture only if it contains the text
583 *xPtr = state.bestX();
584 *yPtr = state.bestY();
588 ///////////////////////////////////////////////////////////////////////////////
590 bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
592 bool hasFixedElements = false;
593 XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
594 viewport.fLeft, viewport.fTop,
595 viewport.width(), viewport.height());
596 // If this is an iframe, accumulate the offset from the parent with
597 // current position, and change the parent pointer.
599 // If this is the top level, take the current position
600 SkPoint parentOffset;
601 parentOffset.set(0,0);
602 if (parentIframeLayer)
603 parentOffset = parentIframeLayer->getPosition();
605 m_iframeOffset = parentOffset + getPosition();
607 parentIframeLayer = this;
611 hasFixedElements = true;
612 // So if this is a fixed layer inside a iframe, use the iframe offset
613 // and the iframe's size as the viewport and pass to the children
614 if (parentIframeLayer) {
615 viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX,
616 parentIframeLayer->m_iframeOffset.fY,
617 parentIframeLayer->getSize().width(),
618 parentIframeLayer->getSize().height());
620 float w = viewport.width();
621 float h = viewport.height();
622 float dx = viewport.fLeft;
623 float dy = viewport.fTop;
627 // It turns out that when it is 'auto', we should use the webkit value
628 // from the original render layer's X,Y, that will take care of alignment
629 // with the parent's layer and fix Margin etc.
630 if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
631 x += m_renderLayerPos.x();
632 else if (m_fixedLeft.defined() || !m_fixedRight.defined())
633 x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
635 x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
637 if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
638 y += m_renderLayerPos.y();
639 else if (m_fixedTop.defined() || !m_fixedBottom.defined())
640 y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
642 y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
644 this->setPosition(x, y);
647 int count = this->countChildren();
648 for (int i = 0; i < count; i++)
649 hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
651 return hasFixedElements;
654 void LayerAndroid::updatePositions()
656 // apply the viewport to us
658 // turn our fields into a matrix.
660 // FIXME: this should happen in the caller, and we should remove these
661 // fields from our subclass
663 GLUtils::toSkMatrix(matrix, m_transform);
664 this->setMatrix(matrix);
667 // now apply it to our children
668 int count = this->countChildren();
669 for (int i = 0; i < count; i++)
670 this->getChild(i)->updatePositions();
673 void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
674 const FloatRect& clipping, float opacity, float scale)
677 IntSize layerSize(getSize().width(), getSize().height());
678 FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY);
679 FloatPoint position(getPosition().fX, getPosition().fY);
680 float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width();
681 float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height();
682 float originX = anchorPoint.x() * layerSize.width();
683 float originY = anchorPoint.y() * layerSize.height();
684 TransformationMatrix localMatrix;
686 localMatrix = parentMatrix;
687 localMatrix.translate3d(originX + position.x(),
688 originY + position.y(),
690 localMatrix.multiply(m_transform);
691 localMatrix.translate3d(-originX,
695 m_atomicSync.unlock();
696 setDrawTransform(localMatrix);
697 if (m_drawTransform.isIdentityOrTranslation()) {
698 // adjust the translation coordinates of the draw transform matrix so
699 // that layers (defined in content coordinates) will align to display/view pixels
700 float desiredContentX = round(m_drawTransform.m41() * scale) / scale;
701 float desiredContentY = round(m_drawTransform.m42() * scale) / scale;
702 XLOG("fudging translation from %f, %f to %f, %f",
703 m_drawTransform.m41(), m_drawTransform.m42(),
704 desiredContentX, desiredContentY);
705 m_drawTransform.setM41(desiredContentX);
706 m_drawTransform.setM42(desiredContentY);
709 m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height());
713 m_atomicSync.unlock();
715 opacity *= getOpacity();
716 setDrawOpacity(opacity);
719 // The clipping rect calculation and intersetion will be done in documents coordinates.
720 FloatRect rect(0, 0, layerSize.width(), layerSize.height());
721 FloatRect clip = m_drawTransform.mapRect(rect);
722 clip.intersect(clipping);
725 setDrawClip(clipping);
728 if (!m_backfaceVisibility
729 && m_drawTransform.inverse().m33() < 0) {
736 int count = this->countChildren();
740 // Flatten to 2D if the layer doesn't preserve 3D.
741 if (!preserves3D()) {
742 localMatrix.setM13(0);
743 localMatrix.setM23(0);
744 localMatrix.setM31(0);
745 localMatrix.setM32(0);
746 localMatrix.setM33(1);
747 localMatrix.setM34(0);
748 localMatrix.setM43(0);
751 // now apply it to our children
753 if (!m_childrenTransform.isIdentity()) {
754 localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
755 localMatrix.multiply(m_childrenTransform);
756 localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
758 for (int i = 0; i < count; i++)
759 this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale);
762 void LayerAndroid::setContentsImage(SkBitmapRef* img)
768 ImagesManager::instance()->addImage(img);
771 bool LayerAndroid::needsTexture()
773 return m_imageRef || (m_recordingPicture
774 && m_recordingPicture->width() && m_recordingPicture->height());
777 void LayerAndroid::removeTexture(PaintedSurface* texture)
779 if (texture == m_texture)
783 IntRect LayerAndroid::clippedRect() const
785 IntRect r(0, 0, getWidth(), getHeight());
786 IntRect tr = m_drawTransform.mapRect(r);
787 IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr);
788 IntRect rect = m_drawTransform.inverse().mapRect(cr);
792 int LayerAndroid::nbLayers()
795 int count = this->countChildren();
796 for (int i = 0; i < count; i++)
797 nb += this->getChild(i)->nbLayers();
801 int LayerAndroid::nbTexturedLayers()
804 int count = this->countChildren();
805 for (int i = 0; i < count; i++)
806 nb += this->getChild(i)->nbTexturedLayers();
812 void LayerAndroid::computeTexturesAmount(TexturesResult* result)
817 int count = this->countChildren();
818 for (int i = 0; i < count; i++)
819 this->getChild(i)->computeTexturesAmount(result);
820 if (m_texture && m_visible)
821 m_texture->computeTexturesAmount(result);
824 void LayerAndroid::showLayer(int indent)
827 memset(spaces, 0, 256);
828 for (int i = 0; i < indent; i++)
832 XLOGC("\n\n--- LAYERS TREE ---");
833 IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
834 XLOGC("documentViewport(%d, %d, %d, %d)",
835 documentViewport.x(), documentViewport.y(),
836 documentViewport.width(), documentViewport.height());
839 IntRect r(0, 0, getWidth(), getHeight());
840 IntRect tr = m_drawTransform.mapRect(r);
841 IntRect visible = visibleArea();
842 IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
843 m_clippingRect.width(), m_clippingRect.height());
844 XLOGC("%s [%d:0x%x] - %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
845 "clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d",
846 spaces, uniqueId(), m_owningLayer,
847 needsTexture() ? "needs a texture" : "no texture",
848 tr.x(), tr.y(), tr.width(), tr.height(),
849 visible.x(), visible.y(), visible.width(), visible.height(),
850 clip.x(), clip.y(), clip.width(), clip.height(),
851 contentIsScrollable() ? "SCROLLABLE" : "",
852 isFixed() ? "FIXED" : "",
854 m_recordingPicture ? m_recordingPicture->width() : -1,
855 m_recordingPicture ? m_recordingPicture->height() : -1);
857 int count = this->countChildren();
858 for (int i = 0; i < count; i++)
859 this->getChild(i)->showLayer(indent + 1);
862 void LayerAndroid::swapTiles()
864 int count = this->countChildren();
865 for (int i = 0; i < count; i++)
866 this->getChild(i)->swapTiles();
869 m_texture->swapTiles();
872 void LayerAndroid::setIsDrawing(bool isDrawing)
874 int count = this->countChildren();
875 for (int i = 0; i < count; i++)
876 this->getChild(i)->setIsDrawing(isDrawing);
879 m_texture->setDrawingLayer(isDrawing ? this : 0);
880 m_texture->clearPaintingLayer();
883 // tell auto-initializing animations to start now
884 KeyframesMap::const_iterator localBegin = m_animations.begin();
885 KeyframesMap::const_iterator localEnd = m_animations.end();
886 for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt)
887 (localIt->second)->suggestBeginTime(WTF::currentTime());
890 void LayerAndroid::setIsPainting(Layer* drawingTree)
892 XLOG("setting layer %p as painting, needs texture %d, drawing tree %p",
893 this, needsTexture(), drawingTree);
894 int count = this->countChildren();
895 for (int i = 0; i < count; i++)
896 this->getChild(i)->setIsPainting(drawingTree);
899 LayerAndroid* drawingLayer = 0;
901 drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId());
903 copyAnimationStartTimes(drawingLayer);
904 obtainTextureForPainting(drawingLayer);
907 void LayerAndroid::copyAnimationStartTimes(LayerAndroid* oldLayer)
912 // copy animation start times, if applicable
913 KeyframesMap::const_iterator localBegin = m_animations.begin();
914 KeyframesMap::const_iterator localEnd = m_animations.end();
915 for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt) {
916 KeyframesMap::const_iterator oldBegin = oldLayer->m_animations.begin();
917 KeyframesMap::const_iterator oldEnd = oldLayer->m_animations.end();
918 for (KeyframesMap::const_iterator oldIt = oldBegin; oldIt != oldEnd; ++oldIt) {
919 if ((localIt->second)->uniqueId() == (oldIt->second)->uniqueId()) {
920 // animations are identical, try to copy start time of the old
921 // one, which will have been initialized some time in the past
922 (localIt->second)->suggestBeginTime((oldIt->second)->beginTime());
928 void LayerAndroid::mergeInvalsInto(Layer* replacementTree)
930 int count = this->countChildren();
931 for (int i = 0; i < count; i++)
932 this->getChild(i)->mergeInvalsInto(replacementTree);
934 LayerAndroid* replacementLayer = static_cast<LayerAndroid*>(replacementTree)->findById(uniqueId());
935 if (replacementLayer)
936 replacementLayer->markAsDirty(m_dirtyRegion);
939 bool LayerAndroid::isReady()
941 int count = countChildren();
942 for (int i = 0; i < count; i++)
943 if (!getChild(i)->isReady())
947 return m_texture->isReady();
948 // TODO: image, check if uploaded?
952 bool LayerAndroid::updateWithTree(LayerAndroid* newTree)
954 // Disable fast update for now
956 bool needsRepaint = false;
957 int count = this->countChildren();
958 for (int i = 0; i < count; i++)
959 needsRepaint |= this->getChild(i)->updateWithTree(newTree);
962 LayerAndroid* newLayer = newTree->findById(uniqueId());
963 needsRepaint |= updateWithLayer(newLayer);
971 // Return true to indicate to WebViewCore that the updates
972 // are too complicated to be fully handled and we need a full
973 // call to webkit (e.g. handle repaints)
974 bool LayerAndroid::updateWithLayer(LayerAndroid* layer)
979 android::AutoMutex lock(m_atomicSync);
980 m_position = layer->m_position;
981 m_anchorPoint = layer->m_anchorPoint;
982 m_size = layer->m_size;
983 m_opacity = layer->m_opacity;
984 m_transform = layer->m_transform;
986 if (m_imageRef != layer->m_imageRef)
989 if ((m_recordingPicture != layer->m_recordingPicture)
990 || (m_imageRef != layer->m_imageRef))
996 void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer)
1002 if (!m_imageTexture) {
1003 m_imageTexture = ImagesManager::instance()->getTextureForImage(m_imageRef);
1004 m_dirtyRegion.setEmpty();
1007 m_texture->setDrawingLayer(0);
1008 m_texture->clearPaintingLayer();
1013 // if a previous tree had the same layer, paint with that painted surface
1014 m_texture = drawingLayer->m_texture;
1018 m_texture = new PaintedSurface();
1020 // pass the invalidated regions to the PaintedSurface
1021 m_texture->setPaintingLayer(this, m_dirtyRegion);
1022 m_dirtyRegion.setEmpty();
1027 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
1029 return a->zValue() > b->zValue();
1032 // We call this in WebViewCore, when copying the tree of layers.
1033 // As we construct a new tree that will be passed on the UI,
1034 // we mark the webkit-side tree as having no more dirty region
1035 // (otherwise we would continuously have those dirty region UI-side)
1036 void LayerAndroid::clearDirtyRegion()
1038 int count = this->countChildren();
1039 for (int i = 0; i < count; i++)
1040 this->getChild(i)->clearDirtyRegion();
1042 m_dirtyRegion.setEmpty();
1045 void LayerAndroid::prepare()
1047 XLOG("LA %p preparing, m_texture %p", this, m_texture);
1049 int count = this->countChildren();
1051 Vector <LayerAndroid*> sublayers;
1052 for (int i = 0; i < count; i++)
1053 sublayers.append(this->getChild(i));
1055 // now we sort for the transparency
1056 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1058 // iterate in reverse so top layers get textures first
1059 for (int i = count-1; i >= 0; i--)
1060 sublayers[i]->prepare();
1064 m_texture->prepare(m_state);
1067 m_imageTexture->prepareGL();
1070 IntRect LayerAndroid::unclippedArea()
1075 area.setWidth(getSize().width());
1076 area.setHeight(getSize().height());
1080 IntRect LayerAndroid::visibleArea()
1082 IntRect area = unclippedArea();
1083 // First, we get the transformed area of the layer,
1084 // in document coordinates
1085 IntRect rect = m_drawTransform.mapRect(area);
1089 // Then we apply the clipping
1090 IntRect clip(m_clippingRect);
1091 rect.intersect(clip);
1093 // Now clip with the viewport in documents coordinate
1094 IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
1095 rect.intersect(documentViewport);
1097 // Finally, let's return the visible area, in layers coordinate
1098 rect.move(-dx, -dy);
1102 bool LayerAndroid::drawCanvas(SkCanvas* canvas)
1107 bool askScreenUpdate = false;
1110 SkAutoCanvasRestore acr(canvas, true);
1112 r.set(m_clippingRect.x(), m_clippingRect.y(),
1113 m_clippingRect.x() + m_clippingRect.width(),
1114 m_clippingRect.y() + m_clippingRect.height());
1115 canvas->clipRect(r);
1117 GLUtils::toSkMatrix(matrix, m_drawTransform);
1118 SkMatrix canvasMatrix = canvas->getTotalMatrix();
1119 matrix.postConcat(canvasMatrix);
1120 canvas->setMatrix(matrix);
1122 layerRect.fLeft = 0;
1124 layerRect.fRight = getWidth();
1125 layerRect.fBottom = getHeight();
1126 onDraw(canvas, m_drawOpacity);
1129 // When the layer is dirty, the UI thread should be notified to redraw.
1130 askScreenUpdate |= drawChildrenCanvas(canvas);
1131 m_atomicSync.lock();
1132 if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
1135 m_atomicSync.unlock();
1136 return askScreenUpdate;
1139 bool LayerAndroid::drawGL()
1141 FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
1142 TilesManager::instance()->shader()->clip(clippingRect);
1146 bool askScreenUpdate = false;
1148 if (m_state->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers) {
1150 askScreenUpdate |= m_texture->draw();
1153 m_imageTexture->drawGL(this);
1156 // When the layer is dirty, the UI thread should be notified to redraw.
1157 askScreenUpdate |= drawChildrenGL();
1158 m_atomicSync.lock();
1159 if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
1162 m_atomicSync.unlock();
1163 return askScreenUpdate;
1166 bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
1168 bool askScreenUpdate = false;
1169 int count = this->countChildren();
1171 Vector <LayerAndroid*> sublayers;
1172 for (int i = 0; i < count; i++)
1173 sublayers.append(this->getChild(i));
1175 // now we sort for the transparency
1176 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1177 for (int i = 0; i < count; i++) {
1178 LayerAndroid* layer = sublayers[i];
1179 askScreenUpdate |= layer->drawCanvas(canvas);
1183 return askScreenUpdate;
1186 bool LayerAndroid::drawChildrenGL()
1188 bool askScreenUpdate = false;
1189 int count = this->countChildren();
1191 Vector <LayerAndroid*> sublayers;
1192 for (int i = 0; i < count; i++)
1193 sublayers.append(this->getChild(i));
1195 // now we sort for the transparency
1196 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1197 for (int i = 0; i < count; i++) {
1198 LayerAndroid* layer = sublayers[i];
1199 askScreenUpdate |= layer->drawGL();
1203 return askScreenUpdate;
1206 void LayerAndroid::contentDraw(SkCanvas* canvas)
1208 if (m_recordingPicture)
1209 canvas->drawPicture(*m_recordingPicture);
1211 if (TilesManager::instance()->getShowVisualIndicator()) {
1212 float w = getSize().width();
1213 float h = getSize().height();
1215 paint.setARGB(128, 255, 0, 0);
1216 canvas->drawLine(0, 0, w, h, paint);
1217 canvas->drawLine(0, h, w, 0, paint);
1218 paint.setARGB(128, 0, 255, 0);
1219 canvas->drawLine(0, 0, 0, h, paint);
1220 canvas->drawLine(0, h, w, h, paint);
1221 canvas->drawLine(w, h, w, 0, paint);
1222 canvas->drawLine(w, 0, 0, 0, paint);
1226 paint.setARGB(80, 255, 0, 0);
1227 canvas->drawRect(m_fixedRect, paint);
1232 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
1236 r.set(0, 0, getSize().width(), getSize().height());
1237 canvas->clipRect(r);
1241 if (!prepareContext())
1244 // we just have this save/restore for opacity...
1245 SkAutoCanvasRestore restore(canvas, true);
1247 int canvasOpacity = SkScalarRound(opacity * 255);
1248 if (canvasOpacity < 255)
1249 canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
1252 if (!m_imageTexture) {
1253 m_imageTexture = ImagesManager::instance()->getTextureForImage(m_imageRef);
1254 m_dirtyRegion.setEmpty();
1256 if (m_imageTexture) {
1258 dest.set(0, 0, getSize().width(), getSize().height());
1259 m_imageTexture->drawCanvas(canvas, dest);
1262 contentDraw(canvas);
1265 SkPicture* LayerAndroid::recordContext()
1267 if (prepareContext(true))
1268 return m_recordingPicture;
1272 bool LayerAndroid::prepareContext(bool force)
1274 if (masksToBounds())
1277 if (force || !m_recordingPicture ||
1278 (m_recordingPicture &&
1279 ((m_recordingPicture->width() != (int) getSize().width()) ||
1280 (m_recordingPicture->height() != (int) getSize().height())))) {
1281 SkSafeUnref(m_recordingPicture);
1282 m_recordingPicture = new SkPicture();
1285 return m_recordingPicture;
1288 SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
1291 if (m_recordingPicture) {
1292 // FIXME: This seems wrong. localToGlobal() applies the full local transform,
1293 // se surely we should operate globalMatrix on size(), not bounds() with
1294 // the position removed? Perhaps we never noticed the bug because most
1295 // layers don't use a local transform?
1296 // See http://b/5338388
1297 SkRect globalRect = bounds();
1298 globalRect.offset(-getPosition()); // localToGlobal adds in position
1299 SkMatrix globalMatrix;
1300 localToGlobal(&globalMatrix);
1301 globalMatrix.mapRect(&globalRect);
1302 SkIRect roundedGlobal;
1303 globalRect.round(&roundedGlobal);
1304 SkIRect iVisibleRect;
1305 visibleRect.round(&iVisibleRect);
1306 SkRegion visRegion(iVisibleRect);
1307 visRegion.op(roundedGlobal, SkRegion::kDifference_Op);
1308 result.set(visRegion.getBounds());
1310 SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)"
1311 "result=(%g,%g,r=%g,b=%g)", __FUNCTION__,
1312 visibleRect.fLeft, visibleRect.fTop,
1313 visibleRect.fRight, visibleRect.fBottom,
1314 globalRect.fLeft, globalRect.fTop,
1315 globalRect.fRight, globalRect.fBottom,
1316 result.fLeft, result.fTop, result.fRight, result.fBottom);
1319 result = visibleRect;
1320 for (int i = 0; i < countChildren(); i++)
1321 result = getChild(i)->subtractLayers(result);
1325 // Debug tools : dump the layers tree in a file.
1326 // The format is simple:
1327 // properties have the form: key = value;
1328 // all statements are finished with a semi-colon.
1332 // - array of elements
1334 // a composed type enclose properties in { and }
1335 // an array enclose composed types in { }, separated with a comma.
1350 void lwrite(FILE* file, const char* str)
1352 fwrite(str, sizeof(char), strlen(str), file);
1355 void writeIndent(FILE* file, int indentLevel)
1358 fprintf(file, "%*s", indentLevel*2, " ");
1361 void writeln(FILE* file, int indentLevel, const char* str)
1363 writeIndent(file, indentLevel);
1368 void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
1370 writeIndent(file, indentLevel);
1371 fprintf(file, "%s = %d;\n", str, value);
1374 void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
1376 writeIndent(file, indentLevel);
1377 fprintf(file, "%s = %x;\n", str, value);
1380 void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
1382 writeIndent(file, indentLevel);
1383 fprintf(file, "%s = %.3f;\n", str, value);
1386 void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
1388 writeIndent(file, indentLevel);
1389 fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
1392 void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
1394 writeIndent(file, indentLevel);
1395 fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
1398 void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
1400 writeIndent(file, indentLevel);
1401 fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
1402 str, rect.fLeft, rect.fTop, rect.width(), rect.height());
1405 void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
1407 if (!length.defined())
1409 writeIndent(file, indentLevel);
1410 fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
1413 void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
1415 writeIndent(file, indentLevel);
1416 fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
1417 "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
1419 matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
1420 matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
1421 matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
1422 matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
1425 void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
1427 writeln(file, indentLevel, "{");
1429 writeHexVal(file, indentLevel + 1, "layer", (int)this);
1430 writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
1431 writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
1432 writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
1433 writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe);
1434 writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
1436 writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
1437 writeSize(file, indentLevel + 1, "size", getSize());
1438 writePoint(file, indentLevel + 1, "position", getPosition());
1439 writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
1441 writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
1442 writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
1443 writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
1446 writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
1447 writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
1448 writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
1449 writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
1450 writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
1451 writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
1452 writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
1453 writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
1454 writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
1457 if (m_recordingPicture) {
1458 writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
1459 writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
1462 if (countChildren()) {
1463 writeln(file, indentLevel + 1, "children = [");
1464 for (int i = 0; i < countChildren(); i++) {
1466 writeln(file, indentLevel + 1, ", ");
1467 getChild(i)->dumpLayers(file, indentLevel + 1);
1469 writeln(file, indentLevel + 1, "];");
1471 writeln(file, indentLevel, "}");
1474 void LayerAndroid::dumpToLog() const
1476 FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
1477 dumpLayers(file, 0);
1479 file = fopen("/data/data/com.android.browser/layertmp", "r");
1481 bzero(buffer, sizeof(buffer));
1482 while (fgets(buffer, sizeof(buffer), file))
1483 SkDebugf("%s", buffer);
1487 LayerAndroid* LayerAndroid::findById(int match)
1489 if (m_uniqueId == match)
1491 for (int i = 0; i < countChildren(); i++) {
1492 LayerAndroid* result = getChild(i)->findById(match);
1499 } // namespace WebCore
1501 #endif // USE(ACCELERATED_COMPOSITING)