2 #include "LayerAndroid.h"
4 #if USE(ACCELERATED_COMPOSITING)
6 #include "AndroidAnimation.h"
7 #include "ClassTracker.h"
10 #include "MediaLayer.h"
11 #include "PaintLayerOperation.h"
12 #include "ParseCanvas.h"
13 #include "SkBitmapRef.h"
14 #include "SkBounder.h"
15 #include "SkDrawFilter.h"
17 #include "SkPicture.h"
18 #include "TilesManager.h"
19 #include <wtf/CurrentTime.h>
21 #define LAYER_DEBUG // Add diagonals for debugging
24 #include <cutils/log.h>
25 #include <wtf/text/CString.h>
26 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
31 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
44 class OpacityDrawFilter : public SkDrawFilter {
46 OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
47 virtual bool filter(SkCanvas* canvas, SkPaint* paint, Type)
49 m_previousOpacity = paint->getAlpha();
50 paint->setAlpha(m_opacity);
53 virtual void restore(SkCanvas* canvas, SkPaint* paint, Type)
55 paint->setAlpha(m_previousOpacity);
59 int m_previousOpacity;
62 ///////////////////////////////////////////////////////////////////////////////
64 LayerAndroid::LayerAndroid(RenderLayer* owner) : SkLayer(),
70 m_recordingPicture(0),
73 m_uniqueId(++gUniqueId),
79 m_lastComputeTextureSize(0),
82 m_backgroundColor = 0;
84 m_preserves3D = false;
86 m_iframeOffset.set(0,0);
88 ClassTracker::instance()->increment("LayerAndroid");
92 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
93 m_haveClip(layer.m_haveClip),
94 m_isIframe(layer.m_isIframe),
95 m_extra(0), // deliberately not copied
96 m_uniqueId(layer.m_uniqueId),
100 m_owningLayer(layer.m_owningLayer)
102 m_isFixed = layer.m_isFixed;
103 m_contentsImage = layer.m_contentsImage;
104 SkSafeRef(m_contentsImage);
105 m_renderLayerPos = layer.m_renderLayerPos;
106 m_transform = layer.m_transform;
107 m_backgroundColor = layer.m_backgroundColor;
109 m_fixedLeft = layer.m_fixedLeft;
110 m_fixedTop = layer.m_fixedTop;
111 m_fixedRight = layer.m_fixedRight;
112 m_fixedBottom = layer.m_fixedBottom;
113 m_fixedMarginLeft = layer.m_fixedMarginLeft;
114 m_fixedMarginTop = layer.m_fixedMarginTop;
115 m_fixedMarginRight = layer.m_fixedMarginRight;
116 m_fixedMarginBottom = layer.m_fixedMarginBottom;
117 m_fixedRect = layer.m_fixedRect;
118 m_iframeOffset = layer.m_iframeOffset;
119 m_recordingPicture = layer.m_recordingPicture;
120 SkSafeRef(m_recordingPicture);
122 m_preserves3D = layer.m_preserves3D;
123 m_anchorPointZ = layer.m_anchorPointZ;
124 m_drawTransform = layer.m_drawTransform;
125 m_childrenTransform = layer.m_childrenTransform;
126 m_dirty = layer.m_dirty;
127 m_pictureUsed = layer.m_pictureUsed;
128 m_scale = layer.m_scale;
129 m_lastComputeTextureSize = 0;
131 for (int i = 0; i < layer.countChildren(); i++)
132 addChild(layer.getChild(i)->copy())->unref();
134 KeyframesMap::const_iterator end = layer.m_animations.end();
135 for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
136 pair<String, int> key((it->second)->name(), (it->second)->type());
137 m_animations.add(key, (it->second)->copy());
141 ClassTracker::instance()->increment("LayerAndroid");
145 LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
149 m_recordingPicture(picture),
154 m_reservedTexture(0),
155 m_requestSent(false),
157 m_lastComputeTextureSize(0),
160 m_backgroundColor = 0;
162 SkSafeRef(m_recordingPicture);
163 m_iframeOffset.set(0,0);
165 ClassTracker::instance()->increment("LayerAndroid");
169 bool LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture)
171 LayerTexture* texture = static_cast<LayerTexture*>(aTexture);
172 android::AutoMutex lock(m_atomicSync);
174 bool textureReleased = true;
175 if (!texture) { // remove ourself from both textures
176 if (m_drawingTexture)
177 textureReleased &= m_drawingTexture->release(this);
178 if (m_reservedTexture &&
179 m_reservedTexture != m_drawingTexture)
180 textureReleased &= m_reservedTexture->release(this);
182 if (m_drawingTexture && m_drawingTexture == texture)
183 textureReleased &= m_drawingTexture->release(this);
184 if (m_reservedTexture &&
185 m_reservedTexture == texture &&
186 m_reservedTexture != m_drawingTexture)
187 textureReleased &= m_reservedTexture->release(this);
189 if (m_drawingTexture &&
190 ((m_drawingTexture->owner() != this) ||
191 (m_drawingTexture->delayedReleaseOwner() == this)))
192 m_drawingTexture = 0;
193 if (m_reservedTexture &&
194 ((m_reservedTexture->owner() != this) ||
195 (m_reservedTexture->delayedReleaseOwner() == this)))
196 m_reservedTexture = 0;
197 return textureReleased;
200 LayerAndroid::~LayerAndroid()
205 SkSafeUnref(m_contentsImage);
206 SkSafeUnref(m_recordingPicture);
207 m_animations.clear();
209 ClassTracker::instance()->decrement("LayerAndroid");
213 static int gDebugNbAnims = 0;
215 bool LayerAndroid::evaluateAnimations()
217 double time = WTF::currentTime();
219 return evaluateAnimations(time);
222 bool LayerAndroid::hasAnimations() const
224 for (int i = 0; i < countChildren(); i++) {
225 if (getChild(i)->hasAnimations())
228 return !!m_animations.size();
231 bool LayerAndroid::evaluateAnimations(double time)
233 bool hasRunningAnimations = false;
234 for (int i = 0; i < countChildren(); i++) {
235 if (getChild(i)->evaluateAnimations(time))
236 hasRunningAnimations = true;
239 m_hasRunningAnimations = false;
241 KeyframesMap::const_iterator end = m_animations.end();
242 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
245 LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
246 if ((it->second)->evaluate(currentLayer, time))
247 m_hasRunningAnimations = true;
250 return hasRunningAnimations || m_hasRunningAnimations;
253 void LayerAndroid::addDirtyArea(GLWebViewState* glWebViewState)
255 IntRect rect(0, 0, getWidth(), getHeight());
256 IntRect dirtyArea = drawTransform().mapRect(rect);
257 IntRect clip(m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.width(), m_clippingRect.height());
258 dirtyArea.intersect(clip);
259 glWebViewState->addDirtyArea(dirtyArea);
262 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
264 RefPtr<AndroidAnimation> anim = prpAnim;
265 pair<String, int> key(anim->name(), anim->type());
266 removeAnimationsForProperty(anim->type());
267 m_animations.add(key, anim);
270 void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
272 KeyframesMap::const_iterator end = m_animations.end();
273 Vector<pair<String, int> > toDelete;
274 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
275 if ((it->second)->type() == property)
276 toDelete.append(it->first);
279 for (unsigned int i = 0; i < toDelete.size(); i++)
280 m_animations.remove(toDelete[i]);
283 void LayerAndroid::removeAnimationsForKeyframes(const String& name)
285 KeyframesMap::const_iterator end = m_animations.end();
286 Vector<pair<String, int> > toDelete;
287 for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
288 if ((it->second)->name() == name)
289 toDelete.append(it->first);
292 for (unsigned int i = 0; i < toDelete.size(); i++)
293 m_animations.remove(toDelete[i]);
296 // We only use the bounding rect of the layer as mask...
297 // TODO: use a real mask?
298 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
304 void LayerAndroid::setBackgroundColor(SkColor color)
306 m_backgroundColor = color;
309 static int gDebugChildLevel;
311 FloatPoint LayerAndroid::translation() const
313 TransformationMatrix::DecomposedType tDecomp;
314 m_transform.decompose(tDecomp);
315 FloatPoint p(tDecomp.translateX, tDecomp.translateY);
319 SkRect LayerAndroid::bounds() const
326 void LayerAndroid::bounds(SkRect* rect) const
328 const SkPoint& pos = this->getPosition();
329 const SkSize& size = this->getSize();
331 // The returned rect has the translation applied
332 // FIXME: apply the full transform to the rect,
333 // and fix the text selection accordingly
334 FloatPoint p(pos.fX, pos.fY);
335 p = m_transform.mapPoint(p);
338 rect->fRight = p.x() + size.width();
339 rect->fBottom = p.y() + size.height();
342 static bool boundsIsUnique(const SkTDArray<SkRect>& region,
345 for (int i = 0; i < region.count(); i++) {
346 if (region[i].contains(local))
352 void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const
355 local.set(0, 0, std::numeric_limits<float>::max(),
356 std::numeric_limits<float>::max());
357 clipInner(region, local);
360 void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
361 const SkRect& local) const
364 bounds(&localBounds);
365 localBounds.intersect(local);
366 if (localBounds.isEmpty())
368 if (m_recordingPicture && boundsIsUnique(*region, localBounds))
369 *region->append() = localBounds;
370 for (int i = 0; i < countChildren(); i++)
371 getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
374 class FindCheck : public SkBounder {
382 bool drew() const { return m_drew; }
383 bool drewText() const { return m_drewText; }
384 void reset() { m_drew = m_drewText = false; }
387 virtual bool onIRect(const SkIRect& )
393 virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& )
395 m_drew = m_drewText = true;
403 class FindCanvas : public ParseCanvas {
405 void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY)
408 translate(-offsetX, -offsetY);
414 class LayerAndroid::FindState {
416 static const int TOUCH_SLOP = 10;
418 FindState(int x, int y)
425 m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2,
427 m_checker.setBounder(&m_findCheck);
428 m_checker.setBitmapDevice(m_bitmap);
431 const LayerAndroid* best() const { return m_best; }
432 int bestX() const { return m_bestX; }
433 int bestY() const { return m_bestY; }
435 bool drew(SkPicture* picture, const SkRect& localBounds)
438 SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft;
439 SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop;
440 m_checker.draw(picture, localX, localY);
441 return m_findCheck.drew();
444 bool drewText() { return m_findCheck.drewText(); }
446 void setBest(const LayerAndroid* best, int x, int y)
452 int x() const { return m_x; }
453 int y() const { return m_y; }
455 void setLocation(int x, int y)
466 const LayerAndroid* m_best;
467 FindCheck m_findCheck;
469 FindCanvas m_checker;
472 void LayerAndroid::findInner(LayerAndroid::FindState& state) const
477 bounds(&localBounds);
478 if (!localBounds.contains(x, y))
480 // Move into local coordinates.
481 state.setLocation(x - localBounds.fLeft, y - localBounds.fTop);
482 for (int i = 0; i < countChildren(); i++)
483 getChild(i)->findInner(state);
484 // Move back into the parent coordinates.
485 int testX = state.x();
486 int testY = state.y();
487 state.setLocation(x + localBounds.fLeft, y + localBounds.fTop);
488 if (!m_recordingPicture)
490 if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds))
492 state.setBest(this, testX, testY); // set last match (presumably on top)
495 const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const
497 FindState state(*xPtr, *yPtr);
499 rootBounds.setEmpty();
500 if (root && state.drew(root, rootBounds) && state.drewText())
501 return 0; // use the root picture only if it contains the text
503 *xPtr = state.bestX();
504 *yPtr = state.bestY();
508 ///////////////////////////////////////////////////////////////////////////////
510 void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
512 // If this is an iframe, accumulate the offset from the parent with
513 // current position, and change the parent pointer.
515 // If this is the top level, take the current position
516 SkPoint parentOffset;
517 parentOffset.set(0,0);
518 if (parentIframeLayer)
519 parentOffset = parentIframeLayer->getPosition();
521 m_iframeOffset = parentOffset + getPosition();
523 parentIframeLayer = this;
527 // So if this is a fixed layer inside a iframe, use the iframe offset
528 // and the iframe's size as the viewport and pass to the children
529 if (parentIframeLayer) {
530 viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX,
531 parentIframeLayer->m_iframeOffset.fY,
532 parentIframeLayer->getSize().width(),
533 parentIframeLayer->getSize().height());
535 float w = viewport.width();
536 float h = viewport.height();
537 float dx = viewport.fLeft;
538 float dy = viewport.fTop;
542 // It turns out that when it is 'auto', the webkit computation will
543 // take one more factor into account, that is the original render
544 // layer's X,Y, such that it will align well with the parent's layer.
545 if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
546 x += m_renderLayerPos.x();
548 if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
549 y += m_renderLayerPos.y();
551 if (m_fixedLeft.defined() || !m_fixedRight.defined())
552 x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
554 x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
556 if (m_fixedTop.defined() || !m_fixedBottom.defined())
557 y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
559 y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
561 this->setPosition(x, y);
564 int count = this->countChildren();
565 for (int i = 0; i < count; i++)
566 this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
569 void LayerAndroid::updatePositions()
571 // apply the viewport to us
573 // turn our fields into a matrix.
575 // TODO: this should happen in the caller, and we should remove these
576 // fields from our subclass
578 GLUtils::toSkMatrix(matrix, m_transform);
579 this->setMatrix(matrix);
582 // now apply it to our children
583 int count = this->countChildren();
584 for (int i = 0; i < count; i++)
585 this->getChild(i)->updatePositions();
588 void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix,
589 const FloatRect& clipping, float opacity)
591 IntSize layerSize(getSize().width(), getSize().height());
592 FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY);
593 FloatPoint position(getPosition().fX, getPosition().fY);
594 float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width();
595 float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height();
596 float originX = anchorPoint.x() * layerSize.width();
597 float originY = anchorPoint.y() * layerSize.height();
598 TransformationMatrix localMatrix;
600 localMatrix = parentMatrix;
601 localMatrix.translate3d(originX + position.x(),
602 originY + position.y(),
604 localMatrix.multLeft(m_transform);
605 localMatrix.translate3d(-originX,
609 setDrawTransform(localMatrix);
610 opacity *= getOpacity();
611 setDrawOpacity(opacity);
614 // The clipping rect calculation and intersetion will be done in Screen Coord now.
616 TilesManager::instance()->shader()->clipRectInScreenCoord(drawTransform(), layerSize);
617 clip.intersect(clipping);
620 setDrawClip(clipping);
623 int count = this->countChildren();
627 // Flatten to 2D if the layer doesn't preserve 3D.
628 if (!preserves3D()) {
629 localMatrix.setM13(0);
630 localMatrix.setM23(0);
631 localMatrix.setM31(0);
632 localMatrix.setM32(0);
633 localMatrix.setM33(1);
634 localMatrix.setM34(0);
635 localMatrix.setM43(0);
638 // now apply it to our children
640 if (!m_childrenTransform.isIdentity()) {
641 localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
642 localMatrix.multLeft(m_childrenTransform);
643 localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
645 for (int i = 0; i < count; i++)
646 this->getChild(i)->updateGLPositions(localMatrix, drawClip(), opacity);
649 void LayerAndroid::setContentsImage(SkBitmapRef* img)
651 SkRefCnt_SafeAssign(m_contentsImage, img);
654 bool LayerAndroid::needsTexture()
656 return m_contentsImage || (prepareContext()
657 && m_recordingPicture->width() && m_recordingPicture->height());
660 IntRect LayerAndroid::clippedRect() const
662 IntRect r(0, 0, getWidth(), getHeight());
663 IntRect tr = drawTransform().mapRect(r);
664 IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr);
665 IntRect rect = drawTransform().inverse().mapRect(cr);
669 bool LayerAndroid::outsideViewport()
671 return m_layerTextureRect.width() == 0 &&
672 m_layerTextureRect.height() == 0;
675 int LayerAndroid::fullTextureSize() const
677 return getWidth() * m_scale * getHeight() * m_scale * 4;
680 int LayerAndroid::clippedTextureSize() const
682 IntRect cr = clippedRect();
683 return cr.width() * cr.height() * 4;
686 int LayerAndroid::countTextureSize()
688 int size = clippedTextureSize();
689 int count = this->countChildren();
690 for (int i = 0; i < count; i++)
691 size += getChild(i)->countTextureSize();
695 int LayerAndroid::nbLayers()
698 int count = this->countChildren();
699 for (int i = 0; i < count; i++)
700 nb += getChild(i)->nbLayers();
704 void LayerAndroid::collect(Vector<LayerAndroid*>& layers, int& size)
706 m_layerTextureRect = clippedRect();
707 if (!outsideViewport()) {
709 size += fullTextureSize();
711 int count = this->countChildren();
712 for (int i = 0; i < count; i++)
713 getChild(i)->collect(layers, size);
716 static inline bool compareLayerFullSize(const LayerAndroid* a, const LayerAndroid* b)
718 const int sizeA = a->fullTextureSize();
719 const int sizeB = b->fullTextureSize();
720 return sizeA > sizeB;
723 void LayerAndroid::computeTextureSize(double time)
725 if (m_lastComputeTextureSize + s_computeTextureDelay > time)
727 m_lastComputeTextureSize = time;
729 // First, we collect the layers, computing m_layerTextureRect
730 // as being clipped against the viewport
731 Vector <LayerAndroid*> layers;
733 collect(layers, total);
735 // Then we sort them by the size the full texture would need
736 std::stable_sort(layers.begin(), layers.end(), compareLayerFullSize);
738 // Now, let's determinate which layer can use a full texture
739 int max = TilesManager::instance()->maxLayersAllocation();
740 int maxLayerSize = TilesManager::instance()->maxLayerAllocation();
741 XLOG("*** layers sorted by size ***");
742 XLOG("total memory needed: %d bytes (%d Mb), max %d Mb",
743 total, total / 1024 / 1024, max / 1024 / 1024);
744 for (unsigned int i = 0; i < layers.size(); i++) {
745 LayerAndroid* layer = layers[i];
747 // If we are under the maximum, and the layer inspected
748 // needs a texture less than the maxLayerSize, use the full texture.
750 (layer->fullTextureSize() < maxLayerSize) &&
751 (layer->getWidth() * m_scale < TilesManager::instance()->getMaxTextureSize()) &&
752 (layer->getHeight() * m_scale < TilesManager::instance()->getMaxTextureSize())) {
753 IntRect full(0, 0, layer->getWidth(), layer->getHeight());
754 layer->m_layerTextureRect = full;
757 // Otherwise, the layer is clipped; update the total
758 total -= layer->fullTextureSize();
759 total += layer->clippedTextureSize();
761 XLOG("Layer %d (%.2f, %.2f) %d bytes (clipped: %s)",
762 layer->uniqueId(), layer->getWidth(), layer->getHeight(),
763 layer->fullTextureSize(),
764 clipped ? "YES" : "NO");
766 XLOG("total memory used after clipping: %d bytes (%d Mb), max %d Mb",
767 total, total / 1024 / 1024, max / 1024 / 1024);
768 XLOG("*** end of sorted layers ***");
771 void LayerAndroid::showLayers(int indent)
773 IntRect cr = clippedRect();
774 int size = cr.width() * cr.height() * 4;
778 for (; p < indent; p++)
782 bool outside = outsideViewport();
783 if (needsTexture() && !outside) {
784 XLOGC("%s Layer %d (%.2f, %.2f), cropped to (%d, %d, %d, %d), using %d Mb",
785 space, uniqueId(), getWidth(), getHeight(),
786 cr.x(), cr.y(), cr.width(), cr.height(), size / 1024 / 1024);
787 } else if (needsTexture() && outside) {
788 XLOGC("%s Layer %d is outside the viewport", space, uniqueId());
790 XLOGC("%s Layer %d has no texture", space, uniqueId());
793 int count = this->countChildren();
794 for (int i = 0; i < count; i++)
795 getChild(i)->showLayers(indent + 1);
798 void LayerAndroid::reserveGLTextures()
800 int count = this->countChildren();
801 for (int i = 0; i < count; i++)
802 this->getChild(i)->reserveGLTextures();
807 if (outsideViewport())
810 LayerTexture* reservedTexture = 0;
811 reservedTexture = TilesManager::instance()->getExistingTextureForLayer(
812 this, m_layerTextureRect);
814 // If we do not have a drawing texture (i.e. new LayerAndroid tree),
815 // we get any one available.
816 if (!m_drawingTexture) {
817 LayerTexture* texture = reservedTexture;
819 TilesManager::instance()->getExistingTextureForLayer(
820 this, m_layerTextureRect, true, texture);
822 if (!m_drawingTexture)
823 m_drawingTexture = reservedTexture;
827 android::AutoMutex lock(m_atomicSync);
828 // we set the reservedTexture if it's different from the drawing texture
829 if (m_reservedTexture != reservedTexture &&
830 ((reservedTexture != m_drawingTexture) ||
831 (m_reservedTexture == 0 && m_drawingTexture == 0))) {
832 // Call release on the reserved texture if it is not the same as the
834 if (m_reservedTexture && (m_reservedTexture != m_drawingTexture))
835 m_reservedTexture->release(this);
836 m_reservedTexture = reservedTexture;
840 void LayerAndroid::createGLTextures()
842 int count = this->countChildren();
843 for (int i = 0; i < count; i++)
844 this->getChild(i)->createGLTextures();
849 if (outsideViewport())
852 LayerTexture* reservedTexture = m_reservedTexture;
853 if (!reservedTexture)
854 reservedTexture = TilesManager::instance()->createTextureForLayer(this, m_layerTextureRect);
856 if (!reservedTexture)
861 m_reservedTexture = reservedTexture;
862 m_atomicSync.unlock();
864 if (reservedTexture &&
865 reservedTexture->ready() &&
866 (reservedTexture != m_drawingTexture)) {
867 if (m_drawingTexture) {
868 TilesManager::instance()->removeOperationsForTexture(m_drawingTexture);
869 m_drawingTexture->release(this);
871 m_drawingTexture = reservedTexture;
874 if (!needsScheduleRepaint(reservedTexture))
878 if (!m_requestSent) {
879 m_requestSent = true;
880 m_atomicSync.unlock();
881 XLOG("We schedule a paint for layer %d (%x), because m_dirty %d, using texture %x (%d, %d)",
882 uniqueId(), this, m_dirty, m_reservedTexture,
883 m_reservedTexture->rect().width(), m_reservedTexture->rect().height());
884 PaintLayerOperation* operation = new PaintLayerOperation(this);
885 TilesManager::instance()->scheduleOperation(operation);
887 XLOG("We don't schedule a paint for layer %d (%x), because we already sent a request",
889 m_atomicSync.unlock();
893 bool LayerAndroid::needsScheduleRepaint(LayerTexture* texture)
898 TextureInfo* textureInfo = texture->consumerLock();
899 if (!texture->readyFor(this))
901 texture->consumerRelease();
906 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
908 const TransformationMatrix& transformA = a->drawTransform();
909 const TransformationMatrix& transformB = b->drawTransform();
911 return transformA.m43() < transformB.m43();
914 bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
916 TilesManager::instance()->shader()->clip(m_clippingRect);
918 if (prepareContext() && m_drawingTexture) {
919 TextureInfo* textureInfo = m_drawingTexture->consumerLock();
922 bounds.set(m_drawingTexture->rect());
923 XLOG("LayerAndroid %d %x (%.2f, %.2f) drawGL (texture %x, %d, %d, %d, %d)",
924 uniqueId(), this, getWidth(), getHeight(),
925 m_drawingTexture, bounds.x(), bounds.y(),
926 bounds.width(), bounds.height());
927 //TODO determine when drawing if the alpha value is used.
928 TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), bounds,
929 textureInfo->m_textureId,
930 m_drawOpacity, true);
932 m_drawingTexture->consumerRelease();
935 // When the layer is dirty, the UI thread should be notified to redraw.
936 bool askPaint = drawChildrenGL(glWebViewState, matrix);
939 if (m_dirty || m_hasRunningAnimations)
940 addDirtyArea(glWebViewState);
941 m_atomicSync.unlock();
946 bool LayerAndroid::drawChildrenGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
948 bool askPaint = false;
949 int count = this->countChildren();
951 Vector <LayerAndroid*> sublayers;
952 for (int i = 0; i < count; i++)
953 sublayers.append(this->getChild(i));
955 // now we sort for the transparency
956 std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
957 for (int i = 0; i < count; i++) {
958 LayerAndroid* layer = sublayers[i];
959 askPaint |= layer->drawGL(glWebViewState, matrix);
966 void LayerAndroid::setScale(float scale)
968 int count = this->countChildren();
969 for (int i = 0; i < count; i++)
970 this->getChild(i)->setScale(scale);
972 android::AutoMutex lock(m_atomicSync);
976 // This is called from the texture generation thread
977 void LayerAndroid::paintBitmapGL()
979 // We acquire the values below atomically. This ensures that we are reading
980 // values correctly across cores. Further, once we have these values they
981 // can be updated by other threads without consequence.
983 LayerTexture* texture = m_reservedTexture;
986 m_atomicSync.unlock();
987 XLOG("Layer %d doesn't have a texture!", uniqueId());
991 XLOG("LayerAndroid %d paintBitmapGL, texture used %x (%d, %d)", uniqueId(), texture,
992 texture->rect().width(), texture->rect().height());
994 // We need to mark the texture as busy before relinquishing the lock
995 // -- so that TilesManager::cleanupLayersTextures() can check if the texture
996 // is used before trying to destroy it
997 // If LayerAndroid::removeTexture() is called before us, we'd have bailed
998 // out early as texture would have been null; if it is called after us, we'd
999 // have marked the texture has being busy, and the texture will not be
1000 // destroyed immediately.
1001 texture->producerAcquireContext();
1002 TextureInfo* textureInfo = texture->producerLock();
1003 m_atomicSync.unlock();
1005 // at this point we can safely check the ownership (if the texture got
1006 // transferred to another BaseTile under us)
1007 if (texture->owner() != this) {
1008 texture->producerRelease();
1012 XLOG("LayerAndroid %d %x (%.2f, %.2f) paintBitmapGL WE ARE PAINTING", uniqueId(), this, getWidth(), getHeight());
1013 SkCanvas* canvas = texture->canvas();
1014 float scale = texture->scale();
1016 IntRect textureRect = texture->rect();
1017 canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
1020 SkCanvas* nCanvas = picture.beginRecording(textureRect.width(),
1021 textureRect.height());
1022 nCanvas->scale(scale, scale);
1023 nCanvas->translate(-textureRect.x(), -textureRect.y());
1024 contentDraw(nCanvas);
1025 picture.endRecording();
1026 picture.draw(canvas);
1028 m_atomicSync.lock();
1029 texture->setTextureInfoFor(this);
1032 m_requestSent = false;
1034 XLOG("LayerAndroid %d paintBitmapGL PAINTING DONE, updating the texture", uniqueId());
1035 texture->producerUpdate(textureInfo);
1037 m_atomicSync.unlock();
1039 XLOG("LayerAndroid %d paintBitmapGL UPDATING DONE", uniqueId());
1042 void LayerAndroid::contentDraw(SkCanvas* canvas)
1044 if (m_contentsImage) {
1046 dest.set(0, 0, getSize().width(), getSize().height());
1047 canvas->drawBitmapRect(m_contentsImage->bitmap(), 0, dest);
1049 canvas->drawPicture(*m_recordingPicture);
1052 m_atomicSync.lock();
1054 canvas->drawPicture(*m_extra);
1055 m_atomicSync.unlock();
1057 if (TilesManager::instance()->getShowVisualIndicator()) {
1058 float w = getSize().width();
1059 float h = getSize().height();
1061 paint.setARGB(128, 255, 0, 0);
1062 canvas->drawLine(0, 0, w, h, paint);
1063 canvas->drawLine(0, h, w, 0, paint);
1064 paint.setARGB(128, 0, 255, 0);
1065 canvas->drawLine(0, 0, 0, h, paint);
1066 canvas->drawLine(0, h, w, h, paint);
1067 canvas->drawLine(w, h, w, 0, paint);
1068 canvas->drawLine(w, 0, 0, 0, paint);
1072 paint.setARGB(80, 255, 0, 0);
1073 canvas->drawRect(m_fixedRect, paint);
1078 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
1082 r.set(0, 0, getSize().width(), getSize().height());
1083 canvas->clipRect(r);
1087 if (!prepareContext())
1090 // we just have this save/restore for opacity...
1091 SkAutoCanvasRestore restore(canvas, true);
1093 int canvasOpacity = SkScalarRound(opacity * 255);
1094 if (canvasOpacity < 255)
1095 canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
1097 contentDraw(canvas);
1100 SkPicture* LayerAndroid::recordContext()
1102 if (prepareContext(true))
1103 return m_recordingPicture;
1107 bool LayerAndroid::prepareContext(bool force)
1109 if (masksToBounds())
1112 if (force || !m_recordingPicture ||
1113 (m_recordingPicture &&
1114 ((m_recordingPicture->width() != (int) getSize().width()) ||
1115 (m_recordingPicture->height() != (int) getSize().height())))) {
1116 SkSafeUnref(m_recordingPicture);
1117 m_recordingPicture = new SkPicture();
1120 return m_recordingPicture;
1123 SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
1126 if (m_recordingPicture) {
1127 SkRect globalRect = bounds();
1128 globalRect.offset(-getPosition()); // localToGlobal adds in position
1129 SkMatrix globalMatrix;
1130 localToGlobal(&globalMatrix);
1131 globalMatrix.mapRect(&globalRect);
1132 SkIRect roundedGlobal;
1133 globalRect.round(&roundedGlobal);
1134 SkIRect iVisibleRect;
1135 visibleRect.round(&iVisibleRect);
1136 SkRegion visRegion(iVisibleRect);
1137 visRegion.op(roundedGlobal, SkRegion::kDifference_Op);
1138 result.set(visRegion.getBounds());
1140 SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)"
1141 "result=(%g,%g,r=%g,b=%g)", __FUNCTION__,
1142 visibleRect.fLeft, visibleRect.fTop,
1143 visibleRect.fRight, visibleRect.fBottom,
1144 globalRect.fLeft, globalRect.fTop,
1145 globalRect.fRight, globalRect.fBottom,
1146 result.fLeft, result.fTop, result.fRight, result.fBottom);
1149 result = visibleRect;
1150 for (int i = 0; i < countChildren(); i++)
1151 result = getChild(i)->subtractLayers(result);
1155 // Debug tools : dump the layers tree in a file.
1156 // The format is simple:
1157 // properties have the form: key = value;
1158 // all statements are finished with a semi-colon.
1162 // - array of elements
1164 // a composed type enclose properties in { and }
1165 // an array enclose composed types in { }, separated with a comma.
1180 void lwrite(FILE* file, const char* str)
1182 fwrite(str, sizeof(char), strlen(str), file);
1185 void writeIndent(FILE* file, int indentLevel)
1188 fprintf(file, "%*s", indentLevel*2, " ");
1191 void writeln(FILE* file, int indentLevel, const char* str)
1193 writeIndent(file, indentLevel);
1198 void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
1200 writeIndent(file, indentLevel);
1201 fprintf(file, "%s = %d;\n", str, value);
1204 void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
1206 writeIndent(file, indentLevel);
1207 fprintf(file, "%s = %x;\n", str, value);
1210 void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
1212 writeIndent(file, indentLevel);
1213 fprintf(file, "%s = %.3f;\n", str, value);
1216 void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
1218 writeIndent(file, indentLevel);
1219 fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
1222 void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
1224 writeIndent(file, indentLevel);
1225 fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
1228 void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
1230 writeIndent(file, indentLevel);
1231 fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
1232 str, rect.fLeft, rect.fTop, rect.width(), rect.height());
1235 void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
1237 if (!length.defined())
1239 writeIndent(file, indentLevel);
1240 fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
1243 void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
1245 writeIndent(file, indentLevel);
1246 fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
1247 "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
1249 matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
1250 matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
1251 matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
1252 matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
1255 void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
1257 writeln(file, indentLevel, "{");
1259 writeHexVal(file, indentLevel + 1, "layer", (int)this);
1260 writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
1261 writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
1262 writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
1263 writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe);
1264 writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
1266 writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
1267 writeSize(file, indentLevel + 1, "size", getSize());
1268 writePoint(file, indentLevel + 1, "position", getPosition());
1269 writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
1271 writeMatrix(file, indentLevel + 1, "drawMatrix", drawTransform());
1272 writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
1275 writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
1276 writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
1277 writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
1278 writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
1279 writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
1280 writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
1281 writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
1282 writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
1283 writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
1286 if (m_recordingPicture) {
1287 writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
1288 writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
1291 if (countChildren()) {
1292 writeln(file, indentLevel + 1, "children = [");
1293 for (int i = 0; i < countChildren(); i++) {
1295 writeln(file, indentLevel + 1, ", ");
1296 getChild(i)->dumpLayers(file, indentLevel + 1);
1298 writeln(file, indentLevel + 1, "];");
1300 writeln(file, indentLevel, "}");
1303 void LayerAndroid::dumpToLog() const
1305 FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
1306 dumpLayers(file, 0);
1308 file = fopen("/data/data/com.android.browser/layertmp", "r");
1310 bzero(buffer, sizeof(buffer));
1311 while (fgets(buffer, sizeof(buffer), file))
1312 SkDebugf("%s", buffer);
1316 LayerAndroid* LayerAndroid::findById(int match)
1318 if (m_uniqueId == match)
1320 for (int i = 0; i < countChildren(); i++) {
1321 LayerAndroid* result = getChild(i)->findById(match);
1328 void LayerAndroid::setExtra(DrawExtra* extra)
1330 for (int i = 0; i < countChildren(); i++)
1331 getChild(i)->setExtra(extra);
1333 android::AutoMutex lock(m_atomicSync);
1334 if (extra || (m_extra && !extra))
1343 if (m_recordingPicture) {
1344 IntRect dummy; // inval area, unused for now
1345 m_extra = new SkPicture();
1346 SkCanvas* canvas = m_extra->beginRecording(m_recordingPicture->width(),
1347 m_recordingPicture->height());
1348 extra->draw(canvas, this, &dummy);
1349 m_extra->endRecording();
1353 } // namespace WebCore
1355 #endif // USE(ACCELERATED_COMPOSITING)