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),
155 m_lastComputeTextureSize(0),
156 m_owningLayer(owner),
157 m_type(LayerAndroid::WebCoreLayer),
160 m_backgroundColor = 0;
162 m_preserves3D = false;
163 m_iframeOffset.set(0,0);
164 m_dirtyRegion.setEmpty();
166 ClassTracker::instance()->increment("LayerAndroid");
167 ClassTracker::instance()->add(this);
171 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
172 m_haveClip(layer.m_haveClip),
173 m_isIframe(layer.m_isIframe),
174 m_uniqueId(layer.m_uniqueId),
176 m_owningLayer(layer.m_owningLayer),
177 m_type(LayerAndroid::UILayer),
180 m_isFixed = layer.m_isFixed;
181 m_imageCRC = layer.m_imageCRC;
183 ImagesManager::instance()->retainImage(m_imageCRC);
185 m_renderLayerPos = layer.m_renderLayerPos;
186 m_transform = layer.m_transform;
187 m_backfaceVisibility = layer.m_backfaceVisibility;
188 m_visible = layer.m_visible;
189 m_backgroundColor = layer.m_backgroundColor;
191 m_fixedLeft = layer.m_fixedLeft;
192 m_fixedTop = layer.m_fixedTop;
193 m_fixedRight = layer.m_fixedRight;
194 m_fixedBottom = layer.m_fixedBottom;
195 m_fixedMarginLeft = layer.m_fixedMarginLeft;
196 m_fixedMarginTop = layer.m_fixedMarginTop;
197 m_fixedMarginRight = layer.m_fixedMarginRight;
198 m_fixedMarginBottom = layer.m_fixedMarginBottom;
199 m_fixedRect = layer.m_fixedRect;
200 m_iframeOffset = layer.m_iframeOffset;
201 m_recordingPicture = layer.m_recordingPicture;
202 SkSafeRef(m_recordingPicture);
204 m_preserves3D = layer.m_preserves3D;
205 m_anchorPointZ = layer.m_anchorPointZ;
206 m_drawTransform = layer.m_drawTransform;
207 m_childrenTransform = layer.m_childrenTransform;
208 m_pictureUsed = layer.m_pictureUsed;
209 m_dirtyRegion = layer.m_dirtyRegion;
210 m_scale = layer.m_scale;
211 m_lastComputeTextureSize = 0;
213 for (int i = 0; i < layer.countChildren(); i++)
214 addChild(layer.getChild(i)->copy())->unref();
216 KeyframesMap::const_iterator end = layer.m_animations.end();
217 for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
218 m_animations.add(it->first, it->second);
221 m_hasText = layer.m_hasText;
224 ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
225 ClassTracker::instance()->add(this);
229 void LayerAndroid::checkTextPresence()
231 if (m_recordingPicture) {
232 // Let's check if we have text or not. If we don't, we can limit
233 // ourselves to scale 1!
234 HasTextBounder hasTextBounder;
235 HasTextCanvas checker(&hasTextBounder, m_recordingPicture);
237 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
238 m_recordingPicture->width(),
239 m_recordingPicture->height());
240 checker.setBitmapDevice(bitmap);
241 checker.drawPicture(*m_recordingPicture);
242 m_hasText = checker.hasText();
246 LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
250 m_recordingPicture(picture),
251 m_uniqueId(++gUniqueId),
255 m_lastComputeTextureSize(0),
257 m_type(LayerAndroid::NavCacheLayer),
260 m_backgroundColor = 0;
261 SkSafeRef(m_recordingPicture);
262 m_iframeOffset.set(0,0);
263 m_dirtyRegion.setEmpty();
265 ClassTracker::instance()->increment("LayerAndroid - from picture");
266 ClassTracker::instance()->add(this);
270 LayerAndroid::~LayerAndroid()
273 ImagesManager::instance()->releaseImage(m_imageCRC);
275 SkSafeUnref(m_recordingPicture);
276 m_animations.clear();
278 ClassTracker::instance()->remove(this);
279 if (m_type == LayerAndroid::WebCoreLayer)
280 ClassTracker::instance()->decrement("LayerAndroid");
281 else if (m_type == LayerAndroid::UILayer)
282 ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)");
283 else if (m_type == LayerAndroid::NavCacheLayer)
284 ClassTracker::instance()->decrement("LayerAndroid - from picture");
288 static int gDebugNbAnims = 0;
290 bool LayerAndroid::evaluateAnimations()
292 double time = WTF::currentTime();
294 return evaluateAnimations(time);
297 bool LayerAndroid::hasAnimations() const
299 for (int i = 0; i < countChildren(); i++) {
300 if (getChild(i)->hasAnimations())
303 return !!m_animations.size();
306 bool LayerAndroid::evaluateAnimations(double time)
308 bool hasRunningAnimations = false;
309 for (int i = 0; i < countChildren(); i++) {
310 if (getChild(i)->evaluateAnimations(time))
311 hasRunningAnimations = true;
314 m_hasRunningAnimations = false;
316 KeyframesMap::const_iterator end = m_animations.end();
317 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
320 LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
321 m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time);
324 return hasRunningAnimations || m_hasRunningAnimations;
327 void LayerAndroid::initAnimations() {
328 // tell auto-initializing animations to start now
329 for (int i = 0; i < countChildren(); i++)
330 getChild(i)->initAnimations();
332 KeyframesMap::const_iterator localBegin = m_animations.begin();
333 KeyframesMap::const_iterator localEnd = m_animations.end();
334 for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt)
335 (localIt->second)->suggestBeginTime(WTF::currentTime());
338 void LayerAndroid::addDirtyArea()
340 IntSize layerSize(getSize().width(), getSize().height());
342 FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize);
343 FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
344 FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect);
346 area.intersect(clip);
347 IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
348 m_state->addDirtyArea(dirtyArea);
351 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
353 RefPtr<AndroidAnimation> anim = prpAnim;
354 pair<String, int> key(anim->name(), anim->type());
355 removeAnimationsForProperty(anim->type());
356 m_animations.add(key, anim);
359 void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
361 KeyframesMap::const_iterator end = m_animations.end();
362 Vector<pair<String, int> > toDelete;
363 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
364 if ((it->second)->type() == property)
365 toDelete.append(it->first);
368 for (unsigned int i = 0; i < toDelete.size(); i++)
369 m_animations.remove(toDelete[i]);
372 void LayerAndroid::removeAnimationsForKeyframes(const String& name)
374 KeyframesMap::const_iterator end = m_animations.end();
375 Vector<pair<String, int> > toDelete;
376 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
377 if ((it->second)->name() == name)
378 toDelete.append(it->first);
381 for (unsigned int i = 0; i < toDelete.size(); i++)
382 m_animations.remove(toDelete[i]);
385 // We only use the bounding rect of the layer as mask...
386 // FIXME: use a real mask?
387 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
393 void LayerAndroid::setBackgroundColor(SkColor color)
395 m_backgroundColor = color;
398 static int gDebugChildLevel;
400 FloatPoint LayerAndroid::translation() const
402 TransformationMatrix::DecomposedType tDecomp;
403 m_transform.decompose(tDecomp);
404 FloatPoint p(tDecomp.translateX, tDecomp.translateY);
408 SkRect LayerAndroid::bounds() const
415 void LayerAndroid::bounds(SkRect* rect) const
417 const SkPoint& pos = this->getPosition();
418 const SkSize& size = this->getSize();
420 // The returned rect has the translation applied
421 // FIXME: apply the full transform to the rect,
422 // and fix the text selection accordingly
423 FloatPoint p(pos.fX, pos.fY);
424 p = m_transform.mapPoint(p);
427 rect->fRight = p.x() + size.width();
428 rect->fBottom = p.y() + size.height();
431 static bool boundsIsUnique(const SkTDArray<SkRect>& region,
434 for (int i = 0; i < region.count(); i++) {
435 if (region[i].contains(local))
441 void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const
444 local.set(0, 0, std::numeric_limits<float>::max(),
445 std::numeric_limits<float>::max());
446 clipInner(region, local);
449 void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
450 const SkRect& local) const
453 bounds(&localBounds);
454 localBounds.intersect(local);
455 if (localBounds.isEmpty())
457 if (m_recordingPicture && boundsIsUnique(*region, localBounds))
458 *region->append() = localBounds;
459 for (int i = 0; i < countChildren(); i++)
460 getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
463 class FindCheck : public SkBounder {
471 bool drew() const { return m_drew; }
472 bool drewText() const { return m_drewText; }
473 void reset() { m_drew = m_drewText = false; }
476 virtual bool onIRect(const SkIRect& )
482 virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& )
484 m_drew = m_drewText = true;
492 class FindCanvas : public ParseCanvas {
494 void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY)
497 translate(-offsetX, -offsetY);
503 class LayerAndroid::FindState {
505 static const int TOUCH_SLOP = 10;
507 FindState(int x, int y)
514 m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2,
516 m_checker.setBounder(&m_findCheck);
517 m_checker.setBitmapDevice(m_bitmap);
520 const LayerAndroid* best() const { return m_best; }
521 int bestX() const { return m_bestX; }
522 int bestY() const { return m_bestY; }
524 bool drew(SkPicture* picture, const SkRect& localBounds)
527 SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft;
528 SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop;
529 m_checker.draw(picture, localX, localY);
530 return m_findCheck.drew();
533 bool drewText() { return m_findCheck.drewText(); }
535 void setBest(const LayerAndroid* best, int x, int y)
541 int x() const { return m_x; }
542 int y() const { return m_y; }
544 void setLocation(int x, int y)
555 const LayerAndroid* m_best;
556 FindCheck m_findCheck;
558 FindCanvas m_checker;
561 void LayerAndroid::findInner(LayerAndroid::FindState& state) const
566 bounds(&localBounds);
567 if (!localBounds.contains(x, y))
569 // Move into local coordinates.
570 state.setLocation(x - localBounds.fLeft, y - localBounds.fTop);
571 for (int i = 0; i < countChildren(); i++)
572 getChild(i)->findInner(state);
573 // Move back into the parent coordinates.
574 int testX = state.x();
575 int testY = state.y();
576 state.setLocation(x + localBounds.fLeft, y + localBounds.fTop);
577 if (!m_recordingPicture)
579 if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds))
581 state.setBest(this, testX, testY); // set last match (presumably on top)
584 const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const
586 FindState state(*xPtr, *yPtr);
588 rootBounds.setEmpty();
589 if (root && state.drew(root, rootBounds) && state.drewText())
590 return 0; // use the root picture only if it contains the text
592 *xPtr = state.bestX();
593 *yPtr = state.bestY();
597 ///////////////////////////////////////////////////////////////////////////////
599 bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
601 bool hasFixedElements = false;
602 XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
603 viewport.fLeft, viewport.fTop,
604 viewport.width(), viewport.height());
605 // If this is an iframe, accumulate the offset from the parent with
606 // current position, and change the parent pointer.
608 // If this is the top level, take the current position
609 SkPoint parentOffset;
610 parentOffset.set(0,0);
611 if (parentIframeLayer)
612 parentOffset = parentIframeLayer->getPosition();
614 m_iframeOffset = parentOffset + getPosition();
616 parentIframeLayer = this;
620 hasFixedElements = true;
621 // So if this is a fixed layer inside a iframe, use the iframe offset
622 // and the iframe's size as the viewport and pass to the children
623 if (parentIframeLayer) {
624 viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX,
625 parentIframeLayer->m_iframeOffset.fY,
626 parentIframeLayer->getSize().width(),
627 parentIframeLayer->getSize().height());
629 float w = viewport.width();
630 float h = viewport.height();
631 float dx = viewport.fLeft;
632 float dy = viewport.fTop;
636 // It turns out that when it is 'auto', we should use the webkit value
637 // from the original render layer's X,Y, that will take care of alignment
638 // with the parent's layer and fix Margin etc.
639 if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
640 x += m_renderLayerPos.x();
641 else if (m_fixedLeft.defined() || !m_fixedRight.defined())
642 x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
644 x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
646 if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
647 y += m_renderLayerPos.y();
648 else if (m_fixedTop.defined() || !m_fixedBottom.defined())
649 y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
651 y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
653 this->setPosition(x, y);
656 int count = this->countChildren();
657 for (int i = 0; i < count; i++)
658 hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
660 return hasFixedElements;
663 void LayerAndroid::updatePositions()
665 // apply the viewport to us
667 // turn our fields into a matrix.
669 // FIXME: this should happen in the caller, and we should remove these
670 // fields from our subclass
672 GLUtils::toSkMatrix(matrix, m_transform);
673 this->setMatrix(matrix);
676 // now apply it to our children
677 int count = this->countChildren();
678 for (int i = 0; i < count; i++)
679 this->getChild(i)->updatePositions();
682 void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
683 const FloatRect& clipping, float opacity, float scale)
686 IntSize layerSize(getSize().width(), getSize().height());
687 FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY);
688 FloatPoint position(getPosition().fX, getPosition().fY);
689 float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width();
690 float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height();
691 float originX = anchorPoint.x() * layerSize.width();
692 float originY = anchorPoint.y() * layerSize.height();
693 TransformationMatrix localMatrix;
695 localMatrix = parentMatrix;
696 localMatrix.translate3d(originX + position.x(),
697 originY + position.y(),
699 localMatrix.multiply(m_transform);
700 localMatrix.translate3d(-originX,
704 m_atomicSync.unlock();
705 setDrawTransform(localMatrix);
706 if (m_drawTransform.isIdentityOrTranslation()) {
707 // adjust the translation coordinates of the draw transform matrix so
708 // that layers (defined in content coordinates) will align to display/view pixels
709 float desiredContentX = round(m_drawTransform.m41() * scale) / scale;
710 float desiredContentY = round(m_drawTransform.m42() * scale) / scale;
711 XLOG("fudging translation from %f, %f to %f, %f",
712 m_drawTransform.m41(), m_drawTransform.m42(),
713 desiredContentX, desiredContentY);
714 m_drawTransform.setM41(desiredContentX);
715 m_drawTransform.setM42(desiredContentY);
718 m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height());
722 m_atomicSync.unlock();
724 opacity *= getOpacity();
725 setDrawOpacity(opacity);
728 // The clipping rect calculation and intersetion will be done in documents coordinates.
729 FloatRect rect(0, 0, layerSize.width(), layerSize.height());
730 FloatRect clip = m_drawTransform.mapRect(rect);
731 clip.intersect(clipping);
734 setDrawClip(clipping);
737 if (!m_backfaceVisibility
738 && m_drawTransform.inverse().m33() < 0) {
745 int count = this->countChildren();
749 // Flatten to 2D if the layer doesn't preserve 3D.
750 if (!preserves3D()) {
751 localMatrix.setM13(0);
752 localMatrix.setM23(0);
753 localMatrix.setM31(0);
754 localMatrix.setM32(0);
755 localMatrix.setM33(1);
756 localMatrix.setM34(0);
757 localMatrix.setM43(0);
760 // now apply it to our children
762 if (!m_childrenTransform.isIdentity()) {
763 localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
764 localMatrix.multiply(m_childrenTransform);
765 localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
767 for (int i = 0; i < count; i++)
768 this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale);
771 void LayerAndroid::setContentsImage(SkBitmapRef* img)
773 ImageTexture* image = ImagesManager::instance()->setImage(img);
774 ImagesManager::instance()->releaseImage(m_imageCRC);
775 m_imageCRC = image ? image->imageCRC() : 0;
778 bool LayerAndroid::needsTexture()
780 return m_imageCRC || (m_recordingPicture
781 && m_recordingPicture->width() && m_recordingPicture->height());
784 void LayerAndroid::removeTexture(PaintedSurface* texture)
786 if (texture == m_texture)
790 IntRect LayerAndroid::clippedRect() const
792 IntRect r(0, 0, getWidth(), getHeight());
793 IntRect tr = m_drawTransform.mapRect(r);
794 IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr);
795 IntRect rect = m_drawTransform.inverse().mapRect(cr);
799 int LayerAndroid::nbLayers()
802 int count = this->countChildren();
803 for (int i = 0; i < count; i++)
804 nb += this->getChild(i)->nbLayers();
808 int LayerAndroid::nbTexturedLayers()
811 int count = this->countChildren();
812 for (int i = 0; i < count; i++)
813 nb += this->getChild(i)->nbTexturedLayers();
819 void LayerAndroid::computeTexturesAmount(TexturesResult* result)
824 int count = this->countChildren();
825 for (int i = 0; i < count; i++)
826 this->getChild(i)->computeTexturesAmount(result);
827 if (m_texture && m_visible)
828 m_texture->computeTexturesAmount(result);
831 void LayerAndroid::showLayer(int indent)
834 memset(spaces, 0, 256);
835 for (int i = 0; i < indent; i++)
839 XLOGC("\n\n--- LAYERS TREE ---");
840 IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
841 XLOGC("documentViewport(%d, %d, %d, %d)",
842 documentViewport.x(), documentViewport.y(),
843 documentViewport.width(), documentViewport.height());
846 IntRect r(0, 0, getWidth(), getHeight());
847 IntRect tr = m_drawTransform.mapRect(r);
848 IntRect visible = visibleArea();
849 IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
850 m_clippingRect.width(), m_clippingRect.height());
851 XLOGC("%s [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
852 "clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d",
853 spaces, uniqueId(), m_owningLayer,
854 needsTexture() ? "needs a texture" : "no texture",
855 m_imageCRC ? "has an image" : "no image",
856 tr.x(), tr.y(), tr.width(), tr.height(),
857 visible.x(), visible.y(), visible.width(), visible.height(),
858 clip.x(), clip.y(), clip.width(), clip.height(),
859 contentIsScrollable() ? "SCROLLABLE" : "",
860 isFixed() ? "FIXED" : "",
862 m_recordingPicture ? m_recordingPicture->width() : -1,
863 m_recordingPicture ? m_recordingPicture->height() : -1);
865 int count = this->countChildren();
866 for (int i = 0; i < count; i++)
867 this->getChild(i)->showLayer(indent + 1);
870 void LayerAndroid::swapTiles()
872 int count = this->countChildren();
873 for (int i = 0; i < count; i++)
874 this->getChild(i)->swapTiles();
877 m_texture->swapTiles();
880 void LayerAndroid::setIsDrawing(bool isDrawing)
882 int count = this->countChildren();
883 for (int i = 0; i < count; i++)
884 this->getChild(i)->setIsDrawing(isDrawing);
887 m_texture->setDrawingLayer(isDrawing ? this : 0);
888 m_texture->clearPaintingLayer();
892 void LayerAndroid::setIsPainting(Layer* drawingTree)
894 XLOG("setting layer %p as painting, needs texture %d, drawing tree %p",
895 this, needsTexture(), drawingTree);
896 int count = this->countChildren();
897 for (int i = 0; i < count; i++)
898 this->getChild(i)->setIsPainting(drawingTree);
901 LayerAndroid* drawingLayer = 0;
903 drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId());
905 obtainTextureForPainting(drawingLayer);
908 void LayerAndroid::mergeInvalsInto(Layer* replacementTree)
910 int count = this->countChildren();
911 for (int i = 0; i < count; i++)
912 this->getChild(i)->mergeInvalsInto(replacementTree);
914 LayerAndroid* replacementLayer = static_cast<LayerAndroid*>(replacementTree)->findById(uniqueId());
915 if (replacementLayer)
916 replacementLayer->markAsDirty(m_dirtyRegion);
919 bool LayerAndroid::isReady()
921 int count = countChildren();
922 for (int i = 0; i < count; i++)
923 if (!getChild(i)->isReady())
927 return m_texture->isReady();
928 // TODO: image, check if uploaded?
932 bool LayerAndroid::updateWithTree(LayerAndroid* newTree)
934 // Disable fast update for now
936 bool needsRepaint = false;
937 int count = this->countChildren();
938 for (int i = 0; i < count; i++)
939 needsRepaint |= this->getChild(i)->updateWithTree(newTree);
942 LayerAndroid* newLayer = newTree->findById(uniqueId());
943 needsRepaint |= updateWithLayer(newLayer);
951 // Return true to indicate to WebViewCore that the updates
952 // are too complicated to be fully handled and we need a full
953 // call to webkit (e.g. handle repaints)
954 bool LayerAndroid::updateWithLayer(LayerAndroid* layer)
959 android::AutoMutex lock(m_atomicSync);
960 m_position = layer->m_position;
961 m_anchorPoint = layer->m_anchorPoint;
962 m_size = layer->m_size;
963 m_opacity = layer->m_opacity;
964 m_transform = layer->m_transform;
966 if (m_imageCRC != layer->m_imageCRC)
969 if ((m_recordingPicture != layer->m_recordingPicture)
970 || (m_imageCRC != layer->m_imageCRC))
976 void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer)
983 m_texture->setDrawingLayer(0);
984 m_texture->clearPaintingLayer();
989 // if a previous tree had the same layer, paint with that painted surface
990 m_texture = drawingLayer->m_texture;
994 m_texture = new PaintedSurface();
996 // pass the invalidated regions to the PaintedSurface
997 m_texture->setPaintingLayer(this, m_dirtyRegion);
999 m_dirtyRegion.setEmpty();
1003 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
1005 return a->zValue() > b->zValue();
1008 // We call this in WebViewCore, when copying the tree of layers.
1009 // As we construct a new tree that will be passed on the UI,
1010 // we mark the webkit-side tree as having no more dirty region
1011 // (otherwise we would continuously have those dirty region UI-side)
1012 void LayerAndroid::clearDirtyRegion()
1014 int count = this->countChildren();
1015 for (int i = 0; i < count; i++)
1016 this->getChild(i)->clearDirtyRegion();
1018 m_dirtyRegion.setEmpty();
1021 void LayerAndroid::prepare()
1023 XLOG("LA %p preparing, m_texture %p", this, m_texture);
1025 int count = this->countChildren();
1027 Vector <LayerAndroid*> sublayers;
1028 for (int i = 0; i < count; i++)
1029 sublayers.append(this->getChild(i));
1031 // now we sort for the transparency
1032 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1034 // iterate in reverse so top layers get textures first
1035 for (int i = count-1; i >= 0; i--)
1036 sublayers[i]->prepare();
1040 m_texture->prepare(m_state);
1043 IntRect LayerAndroid::unclippedArea()
1048 area.setWidth(getSize().width());
1049 area.setHeight(getSize().height());
1053 IntRect LayerAndroid::visibleArea()
1055 IntRect area = unclippedArea();
1056 // First, we get the transformed area of the layer,
1057 // in document coordinates
1058 IntRect rect = m_drawTransform.mapRect(area);
1062 // Then we apply the clipping
1063 IntRect clip(m_clippingRect);
1064 rect.intersect(clip);
1066 // Now clip with the viewport in documents coordinate
1067 IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
1068 rect.intersect(documentViewport);
1070 // Finally, let's return the visible area, in layers coordinate
1071 rect.move(-dx, -dy);
1075 bool LayerAndroid::drawCanvas(SkCanvas* canvas)
1080 bool askScreenUpdate = false;
1083 SkAutoCanvasRestore acr(canvas, true);
1085 r.set(m_clippingRect.x(), m_clippingRect.y(),
1086 m_clippingRect.x() + m_clippingRect.width(),
1087 m_clippingRect.y() + m_clippingRect.height());
1088 canvas->clipRect(r);
1090 GLUtils::toSkMatrix(matrix, m_drawTransform);
1091 SkMatrix canvasMatrix = canvas->getTotalMatrix();
1092 matrix.postConcat(canvasMatrix);
1093 canvas->setMatrix(matrix);
1095 layerRect.fLeft = 0;
1097 layerRect.fRight = getWidth();
1098 layerRect.fBottom = getHeight();
1099 onDraw(canvas, m_drawOpacity);
1102 // When the layer is dirty, the UI thread should be notified to redraw.
1103 askScreenUpdate |= drawChildrenCanvas(canvas);
1104 m_atomicSync.lock();
1105 if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
1108 m_atomicSync.unlock();
1109 return askScreenUpdate;
1112 bool LayerAndroid::drawGL()
1114 FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
1115 TilesManager::instance()->shader()->clip(clippingRect);
1119 bool askScreenUpdate = false;
1121 if (m_state->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers) {
1123 askScreenUpdate |= m_texture->draw();
1125 ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
1127 imageTexture->drawGL(this);
1128 ImagesManager::instance()->releaseImage(m_imageCRC);
1132 // When the layer is dirty, the UI thread should be notified to redraw.
1133 askScreenUpdate |= drawChildrenGL();
1134 m_atomicSync.lock();
1135 if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
1138 m_atomicSync.unlock();
1139 return askScreenUpdate;
1142 bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
1144 bool askScreenUpdate = false;
1145 int count = this->countChildren();
1147 Vector <LayerAndroid*> sublayers;
1148 for (int i = 0; i < count; i++)
1149 sublayers.append(this->getChild(i));
1151 // now we sort for the transparency
1152 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1153 for (int i = 0; i < count; i++) {
1154 LayerAndroid* layer = sublayers[i];
1155 askScreenUpdate |= layer->drawCanvas(canvas);
1159 return askScreenUpdate;
1162 bool LayerAndroid::drawChildrenGL()
1164 bool askScreenUpdate = false;
1165 int count = this->countChildren();
1167 Vector <LayerAndroid*> sublayers;
1168 for (int i = 0; i < count; i++)
1169 sublayers.append(this->getChild(i));
1171 // now we sort for the transparency
1172 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1173 for (int i = 0; i < count; i++) {
1174 LayerAndroid* layer = sublayers[i];
1175 askScreenUpdate |= layer->drawGL();
1179 return askScreenUpdate;
1182 void LayerAndroid::contentDraw(SkCanvas* canvas)
1184 if (m_recordingPicture)
1185 canvas->drawPicture(*m_recordingPicture);
1187 if (TilesManager::instance()->getShowVisualIndicator()) {
1188 float w = getSize().width();
1189 float h = getSize().height();
1191 paint.setARGB(128, 255, 0, 0);
1192 canvas->drawLine(0, 0, w, h, paint);
1193 canvas->drawLine(0, h, w, 0, paint);
1194 paint.setARGB(128, 0, 255, 0);
1195 canvas->drawLine(0, 0, 0, h, paint);
1196 canvas->drawLine(0, h, w, h, paint);
1197 canvas->drawLine(w, h, w, 0, paint);
1198 canvas->drawLine(w, 0, 0, 0, paint);
1202 paint.setARGB(80, 255, 0, 0);
1203 canvas->drawRect(m_fixedRect, paint);
1208 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
1212 r.set(0, 0, getSize().width(), getSize().height());
1213 canvas->clipRect(r);
1217 if (!prepareContext())
1220 // we just have this save/restore for opacity...
1221 SkAutoCanvasRestore restore(canvas, true);
1223 int canvasOpacity = SkScalarRound(opacity * 255);
1224 if (canvasOpacity < 255)
1225 canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
1228 ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
1229 m_dirtyRegion.setEmpty();
1232 dest.set(0, 0, getSize().width(), getSize().height());
1233 imageTexture->drawCanvas(canvas, dest);
1235 ImagesManager::instance()->releaseImage(m_imageCRC);
1237 contentDraw(canvas);
1240 SkPicture* LayerAndroid::recordContext()
1242 if (prepareContext(true))
1243 return m_recordingPicture;
1247 bool LayerAndroid::prepareContext(bool force)
1249 if (masksToBounds())
1252 if (force || !m_recordingPicture ||
1253 (m_recordingPicture &&
1254 ((m_recordingPicture->width() != (int) getSize().width()) ||
1255 (m_recordingPicture->height() != (int) getSize().height())))) {
1256 SkSafeUnref(m_recordingPicture);
1257 m_recordingPicture = new SkPicture();
1260 return m_recordingPicture;
1263 SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
1266 if (m_recordingPicture) {
1267 // FIXME: This seems wrong. localToGlobal() applies the full local transform,
1268 // se surely we should operate globalMatrix on size(), not bounds() with
1269 // the position removed? Perhaps we never noticed the bug because most
1270 // layers don't use a local transform?
1271 // See http://b/5338388
1272 SkRect globalRect = bounds();
1273 globalRect.offset(-getPosition()); // localToGlobal adds in position
1274 SkMatrix globalMatrix;
1275 localToGlobal(&globalMatrix);
1276 globalMatrix.mapRect(&globalRect);
1277 SkIRect roundedGlobal;
1278 globalRect.round(&roundedGlobal);
1279 SkIRect iVisibleRect;
1280 visibleRect.round(&iVisibleRect);
1281 SkRegion visRegion(iVisibleRect);
1282 visRegion.op(roundedGlobal, SkRegion::kDifference_Op);
1283 result.set(visRegion.getBounds());
1285 SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)"
1286 "result=(%g,%g,r=%g,b=%g)", __FUNCTION__,
1287 visibleRect.fLeft, visibleRect.fTop,
1288 visibleRect.fRight, visibleRect.fBottom,
1289 globalRect.fLeft, globalRect.fTop,
1290 globalRect.fRight, globalRect.fBottom,
1291 result.fLeft, result.fTop, result.fRight, result.fBottom);
1294 result = visibleRect;
1295 for (int i = 0; i < countChildren(); i++)
1296 result = getChild(i)->subtractLayers(result);
1300 // Debug tools : dump the layers tree in a file.
1301 // The format is simple:
1302 // properties have the form: key = value;
1303 // all statements are finished with a semi-colon.
1307 // - array of elements
1309 // a composed type enclose properties in { and }
1310 // an array enclose composed types in { }, separated with a comma.
1325 void lwrite(FILE* file, const char* str)
1327 fwrite(str, sizeof(char), strlen(str), file);
1330 void writeIndent(FILE* file, int indentLevel)
1333 fprintf(file, "%*s", indentLevel*2, " ");
1336 void writeln(FILE* file, int indentLevel, const char* str)
1338 writeIndent(file, indentLevel);
1343 void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
1345 writeIndent(file, indentLevel);
1346 fprintf(file, "%s = %d;\n", str, value);
1349 void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
1351 writeIndent(file, indentLevel);
1352 fprintf(file, "%s = %x;\n", str, value);
1355 void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
1357 writeIndent(file, indentLevel);
1358 fprintf(file, "%s = %.3f;\n", str, value);
1361 void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
1363 writeIndent(file, indentLevel);
1364 fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
1367 void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
1369 writeIndent(file, indentLevel);
1370 fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
1373 void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
1375 writeIndent(file, indentLevel);
1376 fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
1377 str, rect.fLeft, rect.fTop, rect.width(), rect.height());
1380 void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
1382 if (!length.defined())
1384 writeIndent(file, indentLevel);
1385 fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
1388 void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
1390 writeIndent(file, indentLevel);
1391 fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
1392 "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
1394 matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
1395 matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
1396 matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
1397 matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
1400 void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
1402 writeln(file, indentLevel, "{");
1404 writeHexVal(file, indentLevel + 1, "layer", (int)this);
1405 writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
1406 writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
1407 writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
1408 writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe);
1409 writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
1411 writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
1412 writeSize(file, indentLevel + 1, "size", getSize());
1413 writePoint(file, indentLevel + 1, "position", getPosition());
1414 writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
1416 writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
1417 writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
1418 writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
1421 writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
1422 writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
1423 writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
1424 writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
1425 writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
1426 writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
1427 writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
1428 writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
1429 writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
1432 if (m_recordingPicture) {
1433 writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
1434 writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
1437 if (countChildren()) {
1438 writeln(file, indentLevel + 1, "children = [");
1439 for (int i = 0; i < countChildren(); i++) {
1441 writeln(file, indentLevel + 1, ", ");
1442 getChild(i)->dumpLayers(file, indentLevel + 1);
1444 writeln(file, indentLevel + 1, "];");
1446 writeln(file, indentLevel, "}");
1449 void LayerAndroid::dumpToLog() const
1451 FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
1452 dumpLayers(file, 0);
1454 file = fopen("/data/data/com.android.browser/layertmp", "r");
1456 bzero(buffer, sizeof(buffer));
1457 while (fgets(buffer, sizeof(buffer), file))
1458 SkDebugf("%s", buffer);
1462 LayerAndroid* LayerAndroid::findById(int match)
1464 if (m_uniqueId == match)
1466 for (int i = 0; i < countChildren(); i++) {
1467 LayerAndroid* result = getChild(i)->findById(match);
1474 } // namespace WebCore
1476 #endif // USE(ACCELERATED_COMPOSITING)