diff options
Diffstat (limited to 'WebCore/platform/graphics/android/LayerAndroid.cpp')
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.cpp | 1402 |
1 files changed, 0 insertions, 1402 deletions
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp deleted file mode 100644 index 7bef420..0000000 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ /dev/null @@ -1,1402 +0,0 @@ -#include "config.h" -#include "LayerAndroid.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "AndroidAnimation.h" -#include "ClassTracker.h" -#include "DrawExtra.h" -#include "GLUtils.h" -#include "MediaLayer.h" -#include "PaintLayerOperation.h" -#include "ParseCanvas.h" -#include "SkBitmapRef.h" -#include "SkBounder.h" -#include "SkDrawFilter.h" -#include "SkPaint.h" -#include "SkPicture.h" -#include "TilesManager.h" -#include <wtf/CurrentTime.h> - -#define LAYER_DEBUG // Add diagonals for debugging -#undef LAYER_DEBUG - -#include <cutils/log.h> -#include <wtf/text/CString.h> -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) - -#ifdef DEBUG - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG - -namespace WebCore { - -static int gUniqueId; - -class OpacityDrawFilter : public SkDrawFilter { - public: - OpacityDrawFilter(int opacity) : m_opacity(opacity) { } - virtual void filter(SkPaint* paint, Type) - { - paint->setAlpha(m_opacity); - } - private: - int m_opacity; -}; - -/////////////////////////////////////////////////////////////////////////////// - -LayerAndroid::LayerAndroid(RenderLayer* owner) : SkLayer(), - m_haveClip(false), - m_isFixed(false), - m_isIframe(false), - m_backfaceVisibility(true), - m_visible(true), - m_preserves3D(false), - m_anchorPointZ(0), - m_recordingPicture(0), - m_contentsImage(0), - m_extra(0), - m_uniqueId(++gUniqueId), - m_drawingTexture(0), - m_reservedTexture(0), - m_pictureUsed(0), - m_requestSent(false), - m_scale(1), - m_lastComputeTextureSize(0), - m_owningLayer(owner) -{ - m_backgroundColor = 0; - - m_preserves3D = false; - m_dirty = false; - m_iframeOffset.set(0,0); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid"); -#endif -} - -LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), - m_haveClip(layer.m_haveClip), - m_isIframe(layer.m_isIframe), - m_contentsImage(0), - m_extra(0), // deliberately not copied - m_uniqueId(layer.m_uniqueId), - m_drawingTexture(0), - m_reservedTexture(0), - m_requestSent(false), - m_owningLayer(layer.m_owningLayer) -{ - m_isFixed = layer.m_isFixed; - copyBitmap(layer.m_contentsImage); - m_renderLayerPos = layer.m_renderLayerPos; - m_transform = layer.m_transform; - m_backfaceVisibility = layer.m_backfaceVisibility; - m_visible = layer.m_visible; - m_backgroundColor = layer.m_backgroundColor; - - m_fixedLeft = layer.m_fixedLeft; - m_fixedTop = layer.m_fixedTop; - m_fixedRight = layer.m_fixedRight; - m_fixedBottom = layer.m_fixedBottom; - m_fixedMarginLeft = layer.m_fixedMarginLeft; - m_fixedMarginTop = layer.m_fixedMarginTop; - m_fixedMarginRight = layer.m_fixedMarginRight; - m_fixedMarginBottom = layer.m_fixedMarginBottom; - m_fixedRect = layer.m_fixedRect; - m_iframeOffset = layer.m_iframeOffset; - m_recordingPicture = layer.m_recordingPicture; - SkSafeRef(m_recordingPicture); - - m_preserves3D = layer.m_preserves3D; - m_anchorPointZ = layer.m_anchorPointZ; - m_drawTransform = layer.m_drawTransform; - m_childrenTransform = layer.m_childrenTransform; - m_dirty = layer.m_dirty; - m_pictureUsed = layer.m_pictureUsed; - m_scale = layer.m_scale; - m_lastComputeTextureSize = 0; - - for (int i = 0; i < layer.countChildren(); i++) - addChild(layer.getChild(i)->copy())->unref(); - - KeyframesMap::const_iterator end = layer.m_animations.end(); - for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { - pair<String, int> key((it->second)->name(), (it->second)->type()); - m_animations.add(key, (it->second)->copy()); - } - -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid"); -#endif -} - -LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), - m_haveClip(false), - m_isFixed(false), - m_isIframe(false), - m_recordingPicture(picture), - m_contentsImage(0), - m_extra(0), - m_uniqueId(-1), - m_drawingTexture(0), - m_reservedTexture(0), - m_requestSent(false), - m_scale(1), - m_lastComputeTextureSize(0), - m_owningLayer(0) -{ - m_backgroundColor = 0; - m_dirty = false; - SkSafeRef(m_recordingPicture); - m_iframeOffset.set(0,0); -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid"); -#endif -} - -bool LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture) -{ - LayerTexture* texture = static_cast<LayerTexture*>(aTexture); - android::AutoMutex lock(m_atomicSync); - - bool textureReleased = true; - if (!texture) { // remove ourself from both textures - if (m_drawingTexture) - textureReleased &= m_drawingTexture->release(this); - if (m_reservedTexture && - m_reservedTexture != m_drawingTexture) - textureReleased &= m_reservedTexture->release(this); - } else { - if (m_drawingTexture && m_drawingTexture == texture) - textureReleased &= m_drawingTexture->release(this); - if (m_reservedTexture && - m_reservedTexture == texture && - m_reservedTexture != m_drawingTexture) - textureReleased &= m_reservedTexture->release(this); - } - if (m_drawingTexture && - ((m_drawingTexture->owner() != this) || - (m_drawingTexture->delayedReleaseOwner() == this))) - m_drawingTexture = 0; - if (m_reservedTexture && - ((m_reservedTexture->owner() != this) || - (m_reservedTexture->delayedReleaseOwner() == this))) - m_reservedTexture = 0; - return textureReleased; -} - -LayerAndroid::~LayerAndroid() -{ - removeTexture(0); - removeChildren(); - delete m_extra; - delete m_contentsImage; - SkSafeUnref(m_recordingPicture); - m_animations.clear(); -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("LayerAndroid"); -#endif -} - -static int gDebugNbAnims = 0; - -bool LayerAndroid::evaluateAnimations() -{ - double time = WTF::currentTime(); - gDebugNbAnims = 0; - return evaluateAnimations(time); -} - -bool LayerAndroid::hasAnimations() const -{ - for (int i = 0; i < countChildren(); i++) { - if (getChild(i)->hasAnimations()) - return true; - } - return !!m_animations.size(); -} - -bool LayerAndroid::evaluateAnimations(double time) -{ - bool hasRunningAnimations = false; - for (int i = 0; i < countChildren(); i++) { - if (getChild(i)->evaluateAnimations(time)) - hasRunningAnimations = true; - } - - m_hasRunningAnimations = false; - int nbAnims = 0; - KeyframesMap::const_iterator end = m_animations.end(); - for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { - gDebugNbAnims++; - nbAnims++; - LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this); - if (!(it->second)->finished() && - (it->second)->evaluate(currentLayer, time)) - m_hasRunningAnimations = true; - } - - return hasRunningAnimations || m_hasRunningAnimations; -} - -void LayerAndroid::addDirtyArea(GLWebViewState* glWebViewState) -{ - IntSize layerSize(getSize().width(), getSize().height()); - - FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(drawTransform(), layerSize); - FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(m_clippingRect); - - area.intersect(clip); - IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); - glWebViewState->addDirtyArea(dirtyArea); -} - -void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim) -{ - RefPtr<AndroidAnimation> anim = prpAnim; - pair<String, int> key(anim->name(), anim->type()); - removeAnimationsForProperty(anim->type()); - m_animations.add(key, anim); -} - -void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property) -{ - KeyframesMap::const_iterator end = m_animations.end(); - Vector<pair<String, int> > toDelete; - for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { - if ((it->second)->type() == property) - toDelete.append(it->first); - } - - for (unsigned int i = 0; i < toDelete.size(); i++) - m_animations.remove(toDelete[i]); -} - -void LayerAndroid::removeAnimationsForKeyframes(const String& name) -{ - KeyframesMap::const_iterator end = m_animations.end(); - Vector<pair<String, int> > toDelete; - for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) { - if ((it->second)->name() == name) - toDelete.append(it->first); - } - - for (unsigned int i = 0; i < toDelete.size(); i++) - m_animations.remove(toDelete[i]); -} - -// We only use the bounding rect of the layer as mask... -// TODO: use a real mask? -void LayerAndroid::setMaskLayer(LayerAndroid* layer) -{ - if (layer) - m_haveClip = true; -} - -void LayerAndroid::setBackgroundColor(SkColor color) -{ - m_backgroundColor = color; -} - -static int gDebugChildLevel; - -FloatPoint LayerAndroid::translation() const -{ - TransformationMatrix::DecomposedType tDecomp; - m_transform.decompose(tDecomp); - FloatPoint p(tDecomp.translateX, tDecomp.translateY); - return p; -} - -SkRect LayerAndroid::bounds() const -{ - SkRect rect; - bounds(&rect); - return rect; -} - -void LayerAndroid::bounds(SkRect* rect) const -{ - const SkPoint& pos = this->getPosition(); - const SkSize& size = this->getSize(); - - // The returned rect has the translation applied - // FIXME: apply the full transform to the rect, - // and fix the text selection accordingly - FloatPoint p(pos.fX, pos.fY); - p = m_transform.mapPoint(p); - rect->fLeft = p.x(); - rect->fTop = p.y(); - rect->fRight = p.x() + size.width(); - rect->fBottom = p.y() + size.height(); -} - -static bool boundsIsUnique(const SkTDArray<SkRect>& region, - const SkRect& local) -{ - for (int i = 0; i < region.count(); i++) { - if (region[i].contains(local)) - return false; - } - return true; -} - -void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const -{ - SkRect local; - local.set(0, 0, std::numeric_limits<float>::max(), - std::numeric_limits<float>::max()); - clipInner(region, local); -} - -void LayerAndroid::clipInner(SkTDArray<SkRect>* region, - const SkRect& local) const -{ - SkRect localBounds; - bounds(&localBounds); - localBounds.intersect(local); - if (localBounds.isEmpty()) - return; - if (m_recordingPicture && boundsIsUnique(*region, localBounds)) - *region->append() = localBounds; - for (int i = 0; i < countChildren(); i++) - getChild(i)->clipInner(region, m_haveClip ? localBounds : local); -} - -class FindCheck : public SkBounder { -public: - FindCheck() - : m_drew(false) - , m_drewText(false) - { - } - - bool drew() const { return m_drew; } - bool drewText() const { return m_drewText; } - void reset() { m_drew = m_drewText = false; } - -protected: - virtual bool onIRect(const SkIRect& ) - { - m_drew = true; - return false; - } - - virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& ) - { - m_drew = m_drewText = true; - return false; - } - - bool m_drew; - bool m_drewText; -}; - -class FindCanvas : public ParseCanvas { -public: - void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY) - { - save(); - translate(-offsetX, -offsetY); - picture->draw(this); - restore(); - } -}; - -class LayerAndroid::FindState { -public: - static const int TOUCH_SLOP = 10; - - FindState(int x, int y) - : m_x(x) - , m_y(y) - , m_bestX(x) - , m_bestY(y) - , m_best(0) - { - m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2, - TOUCH_SLOP * 2); - m_checker.setBounder(&m_findCheck); - m_checker.setBitmapDevice(m_bitmap); - } - - const LayerAndroid* best() const { return m_best; } - int bestX() const { return m_bestX; } - int bestY() const { return m_bestY; } - - bool drew(SkPicture* picture, const SkRect& localBounds) - { - m_findCheck.reset(); - SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft; - SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop; - m_checker.draw(picture, localX, localY); - return m_findCheck.drew(); - } - - bool drewText() { return m_findCheck.drewText(); } - - void setBest(const LayerAndroid* best, int x, int y) - { - m_best = best; - m_bestX = x; - m_bestY = y; - } - int x() const { return m_x; } - int y() const { return m_y; } - - void setLocation(int x, int y) - { - m_x = x; - m_y = y; - } - -protected: - int m_x; - int m_y; - int m_bestX; - int m_bestY; - const LayerAndroid* m_best; - FindCheck m_findCheck; - SkBitmap m_bitmap; - FindCanvas m_checker; -}; - -void LayerAndroid::findInner(LayerAndroid::FindState& state) const -{ - int x = state.x(); - int y = state.y(); - SkRect localBounds; - bounds(&localBounds); - if (!localBounds.contains(x, y)) - return; - // Move into local coordinates. - state.setLocation(x - localBounds.fLeft, y - localBounds.fTop); - for (int i = 0; i < countChildren(); i++) - getChild(i)->findInner(state); - // Move back into the parent coordinates. - int testX = state.x(); - int testY = state.y(); - state.setLocation(x + localBounds.fLeft, y + localBounds.fTop); - if (!m_recordingPicture) - return; - if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds)) - return; - state.setBest(this, testX, testY); // set last match (presumably on top) -} - -const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const -{ - FindState state(*xPtr, *yPtr); - SkRect rootBounds; - rootBounds.setEmpty(); - if (root && state.drew(root, rootBounds) && state.drewText()) - return 0; // use the root picture only if it contains the text - findInner(state); - *xPtr = state.bestX(); - *yPtr = state.bestY(); - return state.best(); -} - -/////////////////////////////////////////////////////////////////////////////// - -void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer) -{ - // If this is an iframe, accumulate the offset from the parent with - // current position, and change the parent pointer. - if (m_isIframe) { - // If this is the top level, take the current position - SkPoint parentOffset; - parentOffset.set(0,0); - if (parentIframeLayer) - parentOffset = parentIframeLayer->getPosition(); - - m_iframeOffset = parentOffset + getPosition(); - - parentIframeLayer = this; - } - - if (m_isFixed) { - // So if this is a fixed layer inside a iframe, use the iframe offset - // and the iframe's size as the viewport and pass to the children - if (parentIframeLayer) { - viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX, - parentIframeLayer->m_iframeOffset.fY, - parentIframeLayer->getSize().width(), - parentIframeLayer->getSize().height()); - } - float w = viewport.width(); - float h = viewport.height(); - float dx = viewport.fLeft; - float dy = viewport.fTop; - float x = dx; - float y = dy; - - // It turns out that when it is 'auto', the webkit computation will - // take one more factor into account, that is the original render - // layer's X,Y, such that it will align well with the parent's layer. - if (!(m_fixedLeft.defined() || m_fixedRight.defined())) - x += m_renderLayerPos.x(); - - if (!(m_fixedTop.defined() || m_fixedBottom.defined())) - y += m_renderLayerPos.y(); - - if (m_fixedLeft.defined() || !m_fixedRight.defined()) - x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft; - else - x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight; - - if (m_fixedTop.defined() || !m_fixedBottom.defined()) - y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop; - else - y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom; - - this->setPosition(x, y); - } - - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer); -} - -void LayerAndroid::updatePositions() -{ - // apply the viewport to us - if (!m_isFixed) { - // turn our fields into a matrix. - // - // TODO: this should happen in the caller, and we should remove these - // fields from our subclass - SkMatrix matrix; - GLUtils::toSkMatrix(matrix, m_transform); - this->setMatrix(matrix); - } - - // now apply it to our children - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->updatePositions(); -} - -void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, - const FloatRect& clipping, float opacity) -{ - IntSize layerSize(getSize().width(), getSize().height()); - FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); - FloatPoint position(getPosition().fX, getPosition().fY); - float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width(); - float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height(); - float originX = anchorPoint.x() * layerSize.width(); - float originY = anchorPoint.y() * layerSize.height(); - TransformationMatrix localMatrix; - if (!m_isFixed) - localMatrix = parentMatrix; - localMatrix.translate3d(originX + position.x(), - originY + position.y(), - anchorPointZ()); - localMatrix.multLeft(m_transform); - localMatrix.translate3d(-originX, - -originY, - -anchorPointZ()); - - setDrawTransform(localMatrix); - m_zValue = TilesManager::instance()->shader()->zValue(drawTransform(), getSize().width(), getSize().height()); - - opacity *= getOpacity(); - setDrawOpacity(opacity); - - if (m_haveClip) { - // The clipping rect calculation and intersetion will be done in Screen Coord now. - FloatRect clip = - TilesManager::instance()->shader()->rectInScreenCoord(drawTransform(), layerSize); - clip.intersect(clipping); - setDrawClip(clip); - } else { - setDrawClip(clipping); - } - - if (!m_backfaceVisibility - && drawTransform().inverse().m33() < 0) { - setVisible(false); - return; - } else { - setVisible(true); - } - - int count = this->countChildren(); - if (!count) - return; - - // Flatten to 2D if the layer doesn't preserve 3D. - if (!preserves3D()) { - localMatrix.setM13(0); - localMatrix.setM23(0); - localMatrix.setM31(0); - localMatrix.setM32(0); - localMatrix.setM33(1); - localMatrix.setM34(0); - localMatrix.setM43(0); - } - - // now apply it to our children - - if (!m_childrenTransform.isIdentity()) { - localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); - localMatrix.multLeft(m_childrenTransform); - localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); - } - for (int i = 0; i < count; i++) - this->getChild(i)->updateGLPositions(localMatrix, drawClip(), opacity); -} - -void LayerAndroid::copyBitmap(SkBitmap* bitmap) -{ - if (!bitmap) - return; - - delete m_contentsImage; - m_contentsImage = new SkBitmap(); - SkBitmap::Config config = bitmap->config(); - int w = bitmap->width(); - int h = bitmap->height(); - m_contentsImage->setConfig(config, w, h); - bitmap->copyTo(m_contentsImage, config); -} - -void LayerAndroid::setContentsImage(SkBitmapRef* img) -{ - copyBitmap(&img->bitmap()); -} - -bool LayerAndroid::needsTexture() -{ - return m_contentsImage || (prepareContext() - && m_recordingPicture->width() && m_recordingPicture->height()); -} - -IntRect LayerAndroid::clippedRect() const -{ - IntRect r(0, 0, getWidth(), getHeight()); - IntRect tr = drawTransform().mapRect(r); - IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr); - IntRect rect = drawTransform().inverse().mapRect(cr); - return rect; -} - -bool LayerAndroid::outsideViewport() -{ - return m_layerTextureRect.width() == 0 && - m_layerTextureRect.height() == 0; -} - -int LayerAndroid::fullTextureSize() const -{ - return getWidth() * m_scale * getHeight() * m_scale * 4; -} - -int LayerAndroid::clippedTextureSize() const -{ - IntRect cr = clippedRect(); - return cr.width() * cr.height() * 4; -} - -int LayerAndroid::countTextureSize() -{ - int size = clippedTextureSize(); - int count = this->countChildren(); - for (int i = 0; i < count; i++) - size += getChild(i)->countTextureSize(); - return size; -} - -int LayerAndroid::nbLayers() -{ - int nb = 1; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - nb += getChild(i)->nbLayers(); - return nb; -} - -void LayerAndroid::collect(Vector<LayerAndroid*>& layers, int& size) -{ - m_layerTextureRect = clippedRect(); - if (!outsideViewport()) { - layers.append(this); - size += fullTextureSize(); - } - int count = this->countChildren(); - for (int i = 0; i < count; i++) - getChild(i)->collect(layers, size); -} - -static inline bool compareLayerFullSize(const LayerAndroid* a, const LayerAndroid* b) -{ - const int sizeA = a->fullTextureSize(); - const int sizeB = b->fullTextureSize(); - return sizeA > sizeB; -} - -void LayerAndroid::computeTextureSize(double time) -{ - if (m_lastComputeTextureSize + s_computeTextureDelay > time) - return; - m_lastComputeTextureSize = time; - - // First, we collect the layers, computing m_layerTextureRect - // as being clipped against the viewport - Vector <LayerAndroid*> layers; - int total = 0; - collect(layers, total); - - // Then we sort them by the size the full texture would need - std::stable_sort(layers.begin(), layers.end(), compareLayerFullSize); - - // Now, let's determinate which layer can use a full texture - int max = TilesManager::instance()->maxLayersAllocation(); - int maxLayerSize = TilesManager::instance()->maxLayerAllocation(); - XLOG("*** layers sorted by size ***"); - XLOG("total memory needed: %d bytes (%d Mb), max %d Mb", - total, total / 1024 / 1024, max / 1024 / 1024); - for (unsigned int i = 0; i < layers.size(); i++) { - LayerAndroid* layer = layers[i]; - bool clipped = true; - // If we are under the maximum, and the layer inspected - // needs a texture less than the maxLayerSize, use the full texture. - if ((total < max) && - (layer->fullTextureSize() < maxLayerSize) && - (layer->getWidth() * m_scale < TilesManager::instance()->getMaxTextureSize()) && - (layer->getHeight() * m_scale < TilesManager::instance()->getMaxTextureSize())) { - IntRect full(0, 0, layer->getWidth(), layer->getHeight()); - layer->m_layerTextureRect = full; - clipped = false; - } else { - // Otherwise, the layer is clipped; update the total - total -= layer->fullTextureSize(); - total += layer->clippedTextureSize(); - } - XLOG("Layer %d (%.2f, %.2f) %d bytes (clipped: %s)", - layer->uniqueId(), layer->getWidth(), layer->getHeight(), - layer->fullTextureSize(), - clipped ? "YES" : "NO"); - } - XLOG("total memory used after clipping: %d bytes (%d Mb), max %d Mb", - total, total / 1024 / 1024, max / 1024 / 1024); - XLOG("*** end of sorted layers ***"); -} - -void LayerAndroid::showLayers(int indent) -{ - IntRect cr = clippedRect(); - int size = cr.width() * cr.height() * 4; - - char space[256]; - int p = 0; - for (; p < indent; p++) - space[p] = ' '; - space[p] = '\0'; - - bool outside = outsideViewport(); - if (needsTexture() && !outside) { - XLOGC("%s Layer %d (%.2f, %.2f), cropped to (%d, %d, %d, %d), using %d Mb", - space, uniqueId(), getWidth(), getHeight(), - cr.x(), cr.y(), cr.width(), cr.height(), size / 1024 / 1024); - } else if (needsTexture() && outside) { - XLOGC("%s Layer %d is outside the viewport", space, uniqueId()); - } else { - XLOGC("%s Layer %d has no texture", space, uniqueId()); - } - - int count = this->countChildren(); - for (int i = 0; i < count; i++) - getChild(i)->showLayers(indent + 1); -} - -void LayerAndroid::reserveGLTextures() -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->reserveGLTextures(); - - if (!needsTexture()) - return; - - if (outsideViewport()) - return; - - LayerTexture* reservedTexture = 0; - reservedTexture = TilesManager::instance()->getExistingTextureForLayer( - this, m_layerTextureRect); - - // If we do not have a drawing texture (i.e. new LayerAndroid tree), - // we get any one available. - if (!m_drawingTexture) { - LayerTexture* texture = reservedTexture; - m_drawingTexture = - TilesManager::instance()->getExistingTextureForLayer( - this, m_layerTextureRect, true, texture); - - if (!m_drawingTexture) - m_drawingTexture = reservedTexture; - } - - // SMP flush - android::AutoMutex lock(m_atomicSync); - // we set the reservedTexture if it's different from the drawing texture - if (m_reservedTexture != reservedTexture && - ((reservedTexture != m_drawingTexture) || - (m_reservedTexture == 0 && m_drawingTexture == 0))) { - // Call release on the reserved texture if it is not the same as the - // drawing texture. - if (m_reservedTexture && (m_reservedTexture != m_drawingTexture)) - m_reservedTexture->release(this); - m_reservedTexture = reservedTexture; - } -} - -void LayerAndroid::createGLTextures() -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->createGLTextures(); - - if (!needsTexture()) - return; - - if (outsideViewport()) - return; - - if (m_drawingTexture && !needsScheduleRepaint(m_drawingTexture)) - return; - - LayerTexture* reservedTexture = m_reservedTexture; - if (!reservedTexture) - reservedTexture = TilesManager::instance()->createTextureForLayer(this, m_layerTextureRect); - - if (!reservedTexture) - return; - - // SMP flush - m_atomicSync.lock(); - m_reservedTexture = reservedTexture; - m_atomicSync.unlock(); - - if (reservedTexture && - reservedTexture->ready() && - (reservedTexture != m_drawingTexture)) { - if (m_drawingTexture) { - TilesManager::instance()->removeOperationsForTexture(m_drawingTexture); - m_drawingTexture->release(this); - } - m_drawingTexture = reservedTexture; - } - - if (!needsScheduleRepaint(reservedTexture)) - return; - - m_atomicSync.lock(); - if (!m_requestSent) { - m_requestSent = true; - m_atomicSync.unlock(); - XLOG("We schedule a paint for layer %d (%x), because m_dirty %d, using texture %x (%d, %d)", - uniqueId(), this, m_dirty, m_reservedTexture, - m_reservedTexture->rect().width(), m_reservedTexture->rect().height()); - PaintLayerOperation* operation = new PaintLayerOperation(this); - TilesManager::instance()->scheduleOperation(operation); - } else { - XLOG("We don't schedule a paint for layer %d (%x), because we already sent a request", - uniqueId(), this); - m_atomicSync.unlock(); - } -} - -bool LayerAndroid::needsScheduleRepaint(LayerTexture* texture) -{ - if (!texture) - return false; - - if (!texture->ready()) { - m_dirty = true; - return true; - } - - TextureInfo* textureInfo = texture->consumerLock(); - if (!texture->readyFor(this) || - (texture->rect() != m_layerTextureRect)) - m_dirty = true; - texture->consumerRelease(); - - return m_dirty; -} - -static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) -{ - return a->zValue() > b->zValue(); -} - -bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) -{ - TilesManager::instance()->shader()->clip(m_clippingRect); - if (!m_visible) - return false; - - if (m_drawingTexture) { - TextureInfo* textureInfo = m_drawingTexture->consumerLock(); - bool ready = m_drawingTexture->readyFor(this); - if (textureInfo && (!m_contentsImage || (ready && m_contentsImage))) { - SkRect bounds; - bounds.set(m_drawingTexture->rect()); - XLOG("LayerAndroid %d %x (%.2f, %.2f) drawGL (texture %x, %d, %d, %d, %d)", - uniqueId(), this, getWidth(), getHeight(), - m_drawingTexture, bounds.x(), bounds.y(), - bounds.width(), bounds.height()); - //TODO determine when drawing if the alpha value is used. - TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), bounds, - textureInfo->m_textureId, - m_drawOpacity, true); - } - if (!ready) - m_dirty = true; - m_drawingTexture->consumerRelease(); - } else if (needsTexture()) { - m_dirty = true; - } - - // When the layer is dirty, the UI thread should be notified to redraw. - bool askPaint = drawChildrenGL(glWebViewState, matrix); - m_atomicSync.lock(); - askPaint |= m_dirty; - if ((m_dirty && needsTexture()) || m_hasRunningAnimations || drawTransform().hasPerspective()) - addDirtyArea(glWebViewState); - - m_atomicSync.unlock(); - return askPaint; -} - - -bool LayerAndroid::drawChildrenGL(GLWebViewState* glWebViewState, SkMatrix& matrix) -{ - bool askPaint = false; - int count = this->countChildren(); - if (count > 0) { - Vector <LayerAndroid*> sublayers; - for (int i = 0; i < count; i++) - sublayers.append(this->getChild(i)); - - // now we sort for the transparency - std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); - for (int i = 0; i < count; i++) { - LayerAndroid* layer = sublayers[i]; - askPaint |= layer->drawGL(glWebViewState, matrix); - } - } - - return askPaint; -} - -void LayerAndroid::setScale(float scale) -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->setScale(scale); - - android::AutoMutex lock(m_atomicSync); - m_scale = scale; -} - -// This is called from the texture generation thread -void LayerAndroid::paintBitmapGL() -{ - // We acquire the values below atomically. This ensures that we are reading - // values correctly across cores. Further, once we have these values they - // can be updated by other threads without consequence. - m_atomicSync.lock(); - LayerTexture* texture = m_reservedTexture; - - if (!texture) { - m_atomicSync.unlock(); - XLOG("Layer %d doesn't have a texture!", uniqueId()); - return; - } - - XLOG("LayerAndroid %d paintBitmapGL, texture used %x (%d, %d)", uniqueId(), texture, - texture->rect().width(), texture->rect().height()); - - // We need to mark the texture as busy before relinquishing the lock - // -- so that TilesManager::cleanupLayersTextures() can check if the texture - // is used before trying to destroy it - // If LayerAndroid::removeTexture() is called before us, we'd have bailed - // out early as texture would have been null; if it is called after us, we'd - // have marked the texture has being busy, and the texture will not be - // destroyed immediately. - texture->producerAcquireContext(); - TextureInfo* textureInfo = texture->producerLock(); - m_atomicSync.unlock(); - - // at this point we can safely check the ownership (if the texture got - // transferred to another BaseTile under us) - if (texture->owner() != this) { - texture->producerRelease(); - return; - } - - XLOG("LayerAndroid %d %x (%.2f, %.2f) paintBitmapGL WE ARE PAINTING", uniqueId(), this, getWidth(), getHeight()); - SkCanvas* canvas = texture->canvas(); - float scale = texture->scale(); - - IntRect textureRect = texture->rect(); - canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); - - if (m_contentsImage) { - contentDraw(canvas); - } else { - SkPicture picture; - SkCanvas* nCanvas = picture.beginRecording(textureRect.width(), - textureRect.height()); - nCanvas->scale(scale, scale); - nCanvas->translate(-textureRect.x(), -textureRect.y()); - contentDraw(nCanvas); - picture.endRecording(); - picture.draw(canvas); - } - extraDraw(canvas); - - m_atomicSync.lock(); - texture->setTextureInfoFor(this); - - m_dirty = false; - m_requestSent = false; - - XLOG("LayerAndroid %d paintBitmapGL PAINTING DONE, updating the texture", uniqueId()); - texture->producerUpdate(textureInfo); - - m_atomicSync.unlock(); - - XLOG("LayerAndroid %d paintBitmapGL UPDATING DONE", uniqueId()); -} - -void LayerAndroid::extraDraw(SkCanvas* canvas) -{ - m_atomicSync.lock(); - if (m_extra) - canvas->drawPicture(*m_extra); - m_atomicSync.unlock(); -} - -void LayerAndroid::contentDraw(SkCanvas* canvas) -{ - if (m_contentsImage) { - SkRect dest; - dest.set(0, 0, getSize().width(), getSize().height()); - canvas->drawBitmapRect(*m_contentsImage, 0, dest); - } else { - canvas->drawPicture(*m_recordingPicture); - } - - if (TilesManager::instance()->getShowVisualIndicator()) { - float w = getSize().width(); - float h = getSize().height(); - SkPaint paint; - paint.setARGB(128, 255, 0, 0); - canvas->drawLine(0, 0, w, h, paint); - canvas->drawLine(0, h, w, 0, paint); - paint.setARGB(128, 0, 255, 0); - canvas->drawLine(0, 0, 0, h, paint); - canvas->drawLine(0, h, w, h, paint); - canvas->drawLine(w, h, w, 0, paint); - canvas->drawLine(w, 0, 0, 0, paint); - - if (m_isFixed) { - SkPaint paint; - paint.setARGB(80, 255, 0, 0); - canvas->drawRect(m_fixedRect, paint); - } - } -} - -void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) -{ - if (m_haveClip) { - SkRect r; - r.set(0, 0, getSize().width(), getSize().height()); - canvas->clipRect(r); - return; - } - - if (!prepareContext()) - return; - - // we just have this save/restore for opacity... - SkAutoCanvasRestore restore(canvas, true); - - int canvasOpacity = SkScalarRound(opacity * 255); - if (canvasOpacity < 255) - canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); - - contentDraw(canvas); -} - -SkPicture* LayerAndroid::recordContext() -{ - if (prepareContext(true)) - return m_recordingPicture; - return 0; -} - -bool LayerAndroid::prepareContext(bool force) -{ - if (masksToBounds()) - return false; - - if (force || !m_recordingPicture || - (m_recordingPicture && - ((m_recordingPicture->width() != (int) getSize().width()) || - (m_recordingPicture->height() != (int) getSize().height())))) { - SkSafeUnref(m_recordingPicture); - m_recordingPicture = new SkPicture(); - } - - return m_recordingPicture; -} - -SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const -{ - SkRect result; - if (m_recordingPicture) { - SkRect globalRect = bounds(); - globalRect.offset(-getPosition()); // localToGlobal adds in position - SkMatrix globalMatrix; - localToGlobal(&globalMatrix); - globalMatrix.mapRect(&globalRect); - SkIRect roundedGlobal; - globalRect.round(&roundedGlobal); - SkIRect iVisibleRect; - visibleRect.round(&iVisibleRect); - SkRegion visRegion(iVisibleRect); - visRegion.op(roundedGlobal, SkRegion::kDifference_Op); - result.set(visRegion.getBounds()); -#if DEBUG_NAV_UI - SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)" - "result=(%g,%g,r=%g,b=%g)", __FUNCTION__, - visibleRect.fLeft, visibleRect.fTop, - visibleRect.fRight, visibleRect.fBottom, - globalRect.fLeft, globalRect.fTop, - globalRect.fRight, globalRect.fBottom, - result.fLeft, result.fTop, result.fRight, result.fBottom); -#endif - } else - result = visibleRect; - for (int i = 0; i < countChildren(); i++) - result = getChild(i)->subtractLayers(result); - return result; -} - -// Debug tools : dump the layers tree in a file. -// The format is simple: -// properties have the form: key = value; -// all statements are finished with a semi-colon. -// value can be: -// - int -// - float -// - array of elements -// - composed type -// a composed type enclose properties in { and } -// an array enclose composed types in { }, separated with a comma. -// exemple: -// { -// x = 3; -// y = 4; -// value = { -// x = 3; -// y = 4; -// }; -// anarray = [ -// { x = 3; }, -// { y = 4; } -// ]; -// } - -void lwrite(FILE* file, const char* str) -{ - fwrite(str, sizeof(char), strlen(str), file); -} - -void writeIndent(FILE* file, int indentLevel) -{ - if (indentLevel) - fprintf(file, "%*s", indentLevel*2, " "); -} - -void writeln(FILE* file, int indentLevel, const char* str) -{ - writeIndent(file, indentLevel); - lwrite(file, str); - lwrite(file, "\n"); -} - -void writeIntVal(FILE* file, int indentLevel, const char* str, int value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %d;\n", str, value); -} - -void writeHexVal(FILE* file, int indentLevel, const char* str, int value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %x;\n", str, value); -} - -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = %.3f;\n", str, value); -} - -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); -} - -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); -} - -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", - str, rect.fLeft, rect.fTop, rect.width(), rect.height()); -} - -void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) -{ - if (!length.defined()) - return; - writeIndent(file, indentLevel); - fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); -} - -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) -{ - writeIndent(file, indentLevel); - fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," - "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", - str, - matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), - matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), - matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), - matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); -} - -void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const -{ - writeln(file, indentLevel, "{"); - - writeHexVal(file, indentLevel + 1, "layer", (int)this); - writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); - writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); - writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed); - writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe); - writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); - - writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); - writeSize(file, indentLevel + 1, "size", getSize()); - writePoint(file, indentLevel + 1, "position", getPosition()); - writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); - - writeMatrix(file, indentLevel + 1, "drawMatrix", drawTransform()); - writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); - - if (m_isFixed) { - writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); - writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); - writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); - writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); - writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); - writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); - writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); - writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); - writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); - } - - if (m_recordingPicture) { - writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width()); - writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height()); - } - - if (countChildren()) { - writeln(file, indentLevel + 1, "children = ["); - for (int i = 0; i < countChildren(); i++) { - if (i > 0) - writeln(file, indentLevel + 1, ", "); - getChild(i)->dumpLayers(file, indentLevel + 1); - } - writeln(file, indentLevel + 1, "];"); - } - writeln(file, indentLevel, "}"); -} - -void LayerAndroid::dumpToLog() const -{ - FILE* file = fopen("/data/data/com.android.browser/layertmp", "w"); - dumpLayers(file, 0); - fclose(file); - file = fopen("/data/data/com.android.browser/layertmp", "r"); - char buffer[512]; - bzero(buffer, sizeof(buffer)); - while (fgets(buffer, sizeof(buffer), file)) - SkDebugf("%s", buffer); - fclose(file); -} - -LayerAndroid* LayerAndroid::findById(int match) -{ - if (m_uniqueId == match) - return this; - for (int i = 0; i < countChildren(); i++) { - LayerAndroid* result = getChild(i)->findById(match); - if (result) - return result; - } - return 0; -} - -void LayerAndroid::setExtra(DrawExtra* extra) -{ - for (int i = 0; i < countChildren(); i++) - getChild(i)->setExtra(extra); - - android::AutoMutex lock(m_atomicSync); - if (extra || (m_extra && !extra)) - m_dirty = true; - - delete m_extra; - m_extra = 0; - - if (!extra) - return; - - if (m_recordingPicture) { - IntRect dummy; // inval area, unused for now - m_extra = new SkPicture(); - SkCanvas* canvas = m_extra->beginRecording(m_recordingPicture->width(), - m_recordingPicture->height()); - extra->draw(canvas, this, &dummy); - m_extra->endRecording(); - } -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) |