diff options
Diffstat (limited to 'WebCore/platform/graphics/android')
16 files changed, 716 insertions, 35 deletions
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp index 7bfbc4e..16e3045 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -121,6 +121,11 @@ bool BackedDoubleBufferedTexture::acquire(TextureOwner* owner) if (m_owner == owner) return true; + return setOwner(owner); +} + +bool BackedDoubleBufferedTexture::setOwner(TextureOwner* owner) +{ // if the writable texture is busy (i.e. currently being written to) then we // can't change the owner out from underneath that texture android::Mutex::Autolock lock(m_busyLock); @@ -139,9 +144,4 @@ void BackedDoubleBufferedTexture::release(TextureOwner* owner) m_owner = 0; } -void BackedDoubleBufferedTexture::release() -{ - m_owner = 0; -} - } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h index 4ffdc07..844715d 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h @@ -53,7 +53,7 @@ public: // updates the texture with current bitmap and releases (and if needed also // swaps) the texture. - void producerUpdate(TextureInfo* textureInfo); + virtual void producerUpdate(TextureInfo* textureInfo); // The level can be one of the following values: // * -1 for an unused texture. @@ -68,7 +68,9 @@ public: // returns false if ownership cannot be transferred because the tile is busy bool acquire(TextureOwner* owner); void release(TextureOwner* owner); - void release(); + + // set the texture owner if not busy. Return false if busy, true otherwise. + bool setOwner(TextureOwner* owner); // private member accessor functions TextureOwner* owner() { return m_owner; } // only used by the consumer thread diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 996b272..040f63e 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -75,6 +75,9 @@ BaseLayerAndroid::BaseLayerAndroid() BaseLayerAndroid::~BaseLayerAndroid() { +#if USE(ACCELERATED_COMPOSITING) + TilesManager::instance()->removeOperationsForBaseLayer(this); +#endif m_content.clear(); #ifdef DEBUG_COUNT gBaseLayerAndroidCount--; @@ -256,6 +259,33 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, ret = drawBasePictureInGL(visibleRect, scale); + if (countChildren() >= 1) { + LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0)); + TransformationMatrix ident; + compositedRoot->updateFixedLayersPositions(visibleRect); + compositedRoot->updateGLPositions(ident, 1); + SkMatrix matrix; + matrix.setTranslate(left, top); + + // At this point, the previous LayerAndroid* root has been destroyed, + // which will have removed the layers as owners of the textures. + // Let's now do a pass to reserve the textures for the current tree; + // it will only reserve existing textures, not create them on demand. +#ifdef DEBUG + TilesManager::instance()->printLayersTextures("reserve"); +#endif + compositedRoot->reserveGLTextures(); + // Now that we marked the textures being used, we delete the unnecessary + // ones to make space... + TilesManager::instance()->cleanupLayersTextures(); + // Finally do another pass to create new textures if needed + compositedRoot->createGLTextures(); + + if (compositedRoot->drawGL(matrix)) + ret = true; + } + glDisable(GL_SCISSOR_TEST); + glBindBuffer(GL_ARRAY_BUFFER, 0); m_previousVisible = visibleRect; diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 5d1c86a..fa660da 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -276,12 +276,23 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) askForSync(); } +void GraphicsLayerAndroid::setPreserves3D(bool preserves3D) +{ + if (preserves3D == m_preserves3D) + return; + + GraphicsLayer::setPreserves3D(preserves3D); + m_contentLayer->setPreserves3D(preserves3D); + askForSync(); +} + void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point) { if (point == m_anchorPoint) return; GraphicsLayer::setAnchorPoint(point); m_contentLayer->setAnchorPoint(point.x(), point.y()); + m_contentLayer->setAnchorPointZ(point.z()); askForSync(); } @@ -303,7 +314,6 @@ void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t) GraphicsLayer::setTransform(t); m_contentLayer->setTransform(t); - askForSync(); } @@ -314,6 +324,7 @@ void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) LOG("(%x) setChildrenTransform", this); GraphicsLayer::setChildrenTransform(t); + m_contentLayer->setChildrenTransform(t); for (unsigned int i = 0; i < m_children.size(); i++) { GraphicsLayer* layer = m_children[i]; layer->setTransform(t); @@ -523,6 +534,7 @@ bool GraphicsLayerAndroid::repaint() m_contentLayer->getSize().width(), m_contentLayer->getSize().height()); + m_contentLayer->needsRepaint(); m_needsRepaint = false; m_invalidatedRects.clear(); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index 1e17f47..a243d65 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -55,6 +55,7 @@ public: virtual void removeFromParent(); virtual void setPosition(const FloatPoint&); + virtual void setPreserves3D(bool b); virtual void setAnchorPoint(const FloatPoint3D&); virtual void setSize(const FloatSize&); diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 15b992a..35a8523 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -6,17 +6,34 @@ #include "AndroidAnimation.h" #include "DrawExtra.h" #include "GLUtils.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 +#ifdef DEBUG + +#include <cutils/log.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + namespace WebCore { static int gDebugLayerAndroidInstances; @@ -51,13 +68,20 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(), m_isRootLayer(isRootLayer), m_haveClip(false), m_isFixed(false), + m_preserves3D(false), + m_anchorPointZ(0), m_recordingPicture(0), m_contentsImage(0), m_extra(0), - m_uniqueId(++gUniqueId) + m_uniqueId(++gUniqueId), + m_texture(0), + m_pictureUsed(0) { m_backgroundColor = 0; + m_preserves3D = false; + m_dirty = false; + gDebugLayerAndroidInstances++; } @@ -65,7 +89,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_isRootLayer(layer.m_isRootLayer), m_haveClip(layer.m_haveClip), m_extra(0), // deliberately not copied - m_uniqueId(layer.m_uniqueId) + m_uniqueId(layer.m_uniqueId), + m_texture(0) { m_isFixed = layer.m_isFixed; m_contentsImage = layer.m_contentsImage; @@ -87,6 +112,13 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), 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; + for (int i = 0; i < layer.countChildren(); i++) addChild(layer.getChild(i)->copy())->unref(); @@ -104,15 +136,19 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), m_recordingPicture(picture), m_contentsImage(0), m_extra(0), - m_uniqueId(-1) + m_uniqueId(-1), + m_texture(0) { m_backgroundColor = 0; + m_dirty = false; SkSafeRef(m_recordingPicture); gDebugLayerAndroidInstances++; } LayerAndroid::~LayerAndroid() { + if (m_texture) + m_texture->release(this); removeChildren(); m_contentsImage->safeUnref(); m_recordingPicture->safeUnref(); @@ -158,6 +194,8 @@ bool LayerAndroid::evaluateAnimations(double time) const void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> anim) { + if (m_animations.get(anim->name())) + removeAnimation(anim->name()); m_animations.add(anim->name(), anim); } @@ -416,13 +454,12 @@ void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport) void LayerAndroid::updatePositions() { // apply the viewport to us - SkMatrix matrix; 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 - matrix.reset(); + SkMatrix matrix; GLUtils::toSkMatrix(matrix, m_transform); this->setMatrix(matrix); } @@ -433,30 +470,214 @@ void LayerAndroid::updatePositions() this->getChild(i)->updatePositions(); } +void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, float opacity) +{ + IntSize bounds(getSize().width(), getSize().height()); + FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY); + FloatPoint position(getPosition().fX, getPosition().fY); + float centerOffsetX = (0.5f - anchorPoint.x()) * bounds.width(); + float centerOffsetY = (0.5f - anchorPoint.y()) * bounds.height(); + float originX = anchorPoint.x() * bounds.width(); + float originY = anchorPoint.y() * bounds.height(); + TransformationMatrix localMatrix = parentMatrix; + localMatrix.translate3d(originX + position.x(), + originY + position.y(), + anchorPointZ()); + FloatPoint p(0, 0); + p = localMatrix.mapPoint(p); + p = m_transform.mapPoint(p); + + localMatrix.multLeft(m_transform); + localMatrix.translate3d(-originX, + -originY, + -anchorPointZ()); + p = localMatrix.mapPoint(p); + + setDrawTransform(localMatrix); + opacity *= getOpacity(); + setDrawOpacity(opacity); + + 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, opacity); +} + void LayerAndroid::setContentsImage(SkBitmapRef* img) { SkRefCnt_SafeAssign(m_contentsImage, img); } -void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) +bool LayerAndroid::needsTexture() { - if (m_haveClip) { - SkRect r; - r.set(0, 0, getSize().width(), getSize().height()); - canvas->clipRect(r); + return !m_isRootLayer && prepareContext() && m_recordingPicture->width() && m_recordingPicture->height(); +} + +void LayerAndroid::reserveGLTextures() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->reserveGLTextures(); + + if (needsTexture()) { + LayerTexture* texture; + texture = TilesManager::instance()->getExistingTextureForLayer(this); + // SMP flush + android::AutoMutex lock(m_atomicSync); + m_texture = texture; + } +} + +void LayerAndroid::createGLTextures() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->createGLTextures(); + + if (needsTexture() && !m_texture) { + LayerTexture* texture; + texture = TilesManager::instance()->createTextureForLayer(this); + // SMP flush + keep dirty bit in sync + android::AutoMutex lock(m_atomicSync); + m_texture = texture; + m_dirty = true; + } + + checkForObsolescence(); +} + +void LayerAndroid::checkForObsolescence() +{ + m_atomicSync.lock(); + if (!m_texture) { + m_atomicSync.unlock(); return; } - if (!prepareContext()) + if (!m_pictureUsed || m_texture->pictureUsed() != m_pictureUsed) { + XLOG("We mark layer %d as dirty because: m_pictureUsed(%d == 0?), texture picture used %x", + uniqueId(), m_pictureUsed, m_texture->pictureUsed()); + m_texture->setPictureUsed(m_pictureUsed); + m_dirty = true; + } + + if (!m_texture->isReady()) + m_dirty = true; + + bool dirty = m_dirty; + m_atomicSync.unlock(); + + if (!dirty) return; - // we just have this save/restore for opacity... - SkAutoCanvasRestore restore(canvas, true); + XLOG("We schedule a paint for layer %d, because isReady %d or m_dirty %d", + uniqueId(), m_texture->isReady(), m_dirty); + PaintLayerOperation* operation = new PaintLayerOperation(this); + TilesManager::instance()->scheduleOperation(operation); +} - int canvasOpacity = SkScalarRound(opacity * 255); - if (canvasOpacity < 255) - canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); +static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) +{ + const TransformationMatrix& transformA = a->drawTransform(); + const TransformationMatrix& transformB = b->drawTransform(); + + return transformA.m43() < transformB.m43(); +} + +bool LayerAndroid::drawGL(SkMatrix& matrix) +{ + if (prepareContext() && m_texture) { + TextureInfo* textureInfo = m_texture->consumerLock(); + if (textureInfo && m_texture->isReady()) { + SkRect rect; + rect.set(0, 0, getSize().width(), getSize().height()); + TransformationMatrix m = drawTransform(); + TilesManager::instance()->shader()->drawLayerQuad(m, rect, + textureInfo->m_textureId, + m_drawOpacity); + } + m_texture->consumerRelease(); + } + + 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(matrix); + } + } + + return askPaint; +} + +// This is called from the texture generation thread +void LayerAndroid::paintBitmapGL() +{ + XLOG("LayerAndroid paintBitmapGL (layer %d)", uniqueId()); + // 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_texture; + m_atomicSync.unlock(); + + if (!texture) { + XLOG("Layer %d doesn't have a texture!", uniqueId()); + return; + } + + texture->producerAcquireContext(); + TextureInfo* textureInfo = texture->producerLock(); + + // 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 paintBitmapGL WE ARE PAINTING", uniqueId()); + SkCanvas* canvas = texture->canvas(); + canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); + contentDraw(canvas); + + XLOG("LayerAndroid %d paintBitmapGL PAINTING DONE, updating the texture", uniqueId()); + m_atomicSync.lock(); + m_dirty = false; + m_atomicSync.unlock(); + texture->producerUpdate(textureInfo); + XLOG("LayerAndroid %d paintBitmapGL UPDATING DONE", uniqueId()); +} + +void LayerAndroid::contentDraw(SkCanvas* canvas) +{ if (m_contentsImage) { SkRect dest; dest.set(0, 0, getSize().width(), getSize().height()); @@ -490,6 +711,28 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) #endif } +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)) diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 1269a1d..3d1c5af 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -19,9 +19,13 @@ #if USE(ACCELERATED_COMPOSITING) +#include "FloatPoint.h" +#include "FloatPoint3D.h" +#include "LayerTexture.h" #include "RefPtr.h" #include "SkColor.h" #include "SkLayer.h" +#include "TextureOwner.h" #include "TransformationMatrix.h" #include <wtf/HashMap.h> @@ -76,8 +80,11 @@ struct SkLength { namespace WebCore { class AndroidAnimation; +class BackedDoubleBufferedTexture; +class LayerAndroidFindState; +class TiledPage; -class LayerAndroid : public SkLayer { +class LayerAndroid : public SkLayer, public TextureOwner { public: LayerAndroid(bool isRootLayer); @@ -85,11 +92,39 @@ public: LayerAndroid(SkPicture*); virtual ~LayerAndroid(); + // TextureOwner methods + virtual void removeTexture() + { + android::AutoMutex lock(m_atomicSync); + m_texture = 0; + } + virtual TiledPage* page() { return 0; } + static int instancesCount(); void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } FloatPoint translation() const; SkRect bounds() const; + // called on the root layer + void reserveGLTextures(); + void createGLTextures(); + + bool needsTexture(); + void checkForObsolescence(); + + bool drawGL(SkMatrix&); + void paintBitmapGL(); + void updateGLPositions(const TransformationMatrix& parentMatrix, float opacity); + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + + bool preserves3D() { return m_preserves3D; } + void setPreserves3D(bool value) { m_preserves3D = value; } + void setAnchorPointZ(float z) { m_anchorPointZ = z; } + float anchorPointZ() { return m_anchorPointZ; } + void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } + const TransformationMatrix& drawTransform() const { return m_drawTransform; } + void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } + void setFixedPosition(SkLength left, // CSS left property SkLength top, // CSS top property SkLength right, // CSS right property @@ -177,12 +212,17 @@ public: m_recordingPicture and m_contentsImage. */ void setContentsImage(SkBitmapRef* img); + bool hasContentsImage() { return m_contentsImage; } void bounds(SkRect*) const; virtual bool contentIsScrollable() const { return false; } virtual LayerAndroid* copy() const { return new LayerAndroid(*this); } + void needsRepaint() { m_pictureUsed++; } + unsigned int pictureUsed() { return m_pictureUsed; } + void contentDraw(SkCanvas*); + protected: virtual void onDraw(SkCanvas*, SkScalar opacity); @@ -216,6 +256,12 @@ private: SkColor m_backgroundColor; + bool m_preserves3D; + float m_anchorPointZ; + float m_drawOpacity; + TransformationMatrix m_drawTransform; + TransformationMatrix m_childrenTransform; + // Note that m_recordingPicture and m_contentsImage are mutually exclusive; // m_recordingPicture is used when WebKit is asked to paint the layer's // content, while m_contentsImage contains an image that we directly @@ -231,6 +277,17 @@ private: DrawExtra* m_extra; int m_uniqueId; + // GL textures management + LayerTexture* m_texture; + // used to signal that the tile is out-of-date and needs to be redrawn + bool m_dirty; + unsigned int m_pictureUsed; + + // This mutex serves two purposes. (1) It ensures that certain operations + // happen atomically and (2) it makes sure those operations are synchronized + // across all threads and cores. + android::Mutex m_atomicSync; + typedef SkLayer INHERITED; }; diff --git a/WebCore/platform/graphics/android/LayerTexture.cpp b/WebCore/platform/graphics/android/LayerTexture.cpp new file mode 100644 index 0000000..294c3d3 --- /dev/null +++ b/WebCore/platform/graphics/android/LayerTexture.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LayerTexture.h" + +#define DOUBLE_BUFFERED_TEXTURE_MINIMUM_ACCESS 3 + +void LayerTexture::producerUpdate(TextureInfo* textureInfo) +{ + update(); + BackedDoubleBufferedTexture::producerUpdate(textureInfo); +} + +void LayerTexture::update() +{ + // FIXME: fix the double buffered texture class instead of doing this + // this is a stop gap measure and should be removed. + // Right now we have to update the textures 3 times (one create, two + // updates) before we can be sure to have a non-corrupted texture + // to display. + if (m_textureUpdates < DOUBLE_BUFFERED_TEXTURE_MINIMUM_ACCESS) + m_textureUpdates++; +} + +bool LayerTexture::isReady() +{ + return m_textureUpdates == DOUBLE_BUFFERED_TEXTURE_MINIMUM_ACCESS; +} diff --git a/WebCore/platform/graphics/android/LayerTexture.h b/WebCore/platform/graphics/android/LayerTexture.h new file mode 100644 index 0000000..959978f --- /dev/null +++ b/WebCore/platform/graphics/android/LayerTexture.h @@ -0,0 +1,61 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LayerTexture_h +#define LayerTexture_h + +#include "BackedDoubleBufferedTexture.h" + +namespace WebCore { + +class LayerTexture : public BackedDoubleBufferedTexture { + public: + LayerTexture(uint32_t w, uint32_t h, + SkBitmap::Config config = SkBitmap::kARGB_8888_Config) + : BackedDoubleBufferedTexture(w, h, config) + , m_id(0) + , m_pictureUsed(0) + , m_textureUpdates(0) + {} + + int id() { return m_id; } + void setId(int id) { m_id = id; } + + unsigned int pictureUsed() { return m_pictureUsed; } + void setPictureUsed(unsigned pictureUsed) { m_pictureUsed = pictureUsed; } + bool isReady(); + virtual void producerUpdate(TextureInfo* textureInfo); + + private: + void update(); + + int m_id; + unsigned int m_pictureUsed; + unsigned int m_textureUpdates; +}; + +} // namespace WebCore + +#endif // LayerTexture_h diff --git a/WebCore/platform/graphics/android/PaintLayerOperation.cpp b/WebCore/platform/graphics/android/PaintLayerOperation.cpp new file mode 100644 index 0000000..a3ef148 --- /dev/null +++ b/WebCore/platform/graphics/android/PaintLayerOperation.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PaintLayerOperation.h" + +#include "LayerAndroid.h" + +bool PaintLayerOperation::operator==(const QueuedOperation* operation) +{ + if (operation->type() != type()) + return false; + const PaintLayerOperation* op = static_cast<const PaintLayerOperation*>(operation); + return op->m_layer == m_layer; +} + +void PaintLayerOperation::run() +{ + if (m_layer) + m_layer->paintBitmapGL(); +} + +SkLayer* PaintLayerOperation::baseLayer() +{ + if (!m_layer) + return 0; + + return m_layer->getRootLayer(); +} + +bool PaintLayerFilter::check(QueuedOperation* operation) +{ + if (operation->type() == QueuedOperation::PaintLayer) { + PaintLayerOperation* op = static_cast<PaintLayerOperation*>(operation); + if (op->baseLayer() == m_baseLayer) + return true; + } + return false; +} diff --git a/WebCore/platform/graphics/android/PaintLayerOperation.h b/WebCore/platform/graphics/android/PaintLayerOperation.h new file mode 100644 index 0000000..d393ac5 --- /dev/null +++ b/WebCore/platform/graphics/android/PaintLayerOperation.h @@ -0,0 +1,62 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PaintLayerOperation_h +#define PaintLayerOperation_h + +#include "QueuedOperation.h" + +class SkLayer; + +namespace WebCore { + +class LayerAndroid; + +class PaintLayerOperation : public QueuedOperation { + public: + PaintLayerOperation(LayerAndroid* layer) + : QueuedOperation(QueuedOperation::PaintLayer, 0) + , m_layer(layer) {} + virtual ~PaintLayerOperation() {} + virtual bool operator==(const QueuedOperation* operation); + virtual void run(); + SkLayer* baseLayer(); + + private: + LayerAndroid* m_layer; +}; + +class PaintLayerFilter : public OperationFilter { + public: + PaintLayerFilter(SkLayer* layer) : m_baseLayer(layer) {} + virtual bool check(QueuedOperation* operation); + + private: + SkLayer* m_baseLayer; +}; + +} + +#endif // PaintLayerOperation_h diff --git a/WebCore/platform/graphics/android/QueuedOperation.h b/WebCore/platform/graphics/android/QueuedOperation.h index 7472db7..089483d 100644 --- a/WebCore/platform/graphics/android/QueuedOperation.h +++ b/WebCore/platform/graphics/android/QueuedOperation.h @@ -32,7 +32,7 @@ namespace WebCore { class QueuedOperation { public: - enum OperationType { Undefined, PaintTileSet, DeleteTexture }; + enum OperationType { Undefined, PaintTileSet, PaintLayer, DeleteTexture }; QueuedOperation(OperationType type, TiledPage* page) : m_type(type) , m_page(page) {} @@ -46,15 +46,13 @@ class QueuedOperation { TiledPage* m_page; }; -class OperationFilter -{ +class OperationFilter { public: - virtual ~OperationFilter() {} - virtual bool check(QueuedOperation* operation) = 0; + virtual ~OperationFilter() {} + virtual bool check(QueuedOperation* operation) = 0; }; -class PageFilter : public OperationFilter -{ +class PageFilter : public OperationFilter { public: PageFilter(TiledPage* page) : m_page(page) {} virtual bool check(QueuedOperation* operation) diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp index 234c7f9..289665d 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -28,7 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) +#include "BaseLayerAndroid.h" #include "GLUtils.h" +#include "PaintLayerOperation.h" #include "TilesManager.h" #ifdef DEBUG @@ -76,6 +78,11 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page) removeOperationsForFilter(new PageFilter(page)); } +void TexturesGenerator::removeOperationsForBaseLayer(BaseLayerAndroid* layer) +{ + removeOperationsForFilter(new PaintLayerFilter(layer)); +} + void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) { mRequestedOperationsLock.lock(); diff --git a/WebCore/platform/graphics/android/TexturesGenerator.h b/WebCore/platform/graphics/android/TexturesGenerator.h index 84dbeab..0e40e4a 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/WebCore/platform/graphics/android/TexturesGenerator.h @@ -37,6 +37,9 @@ namespace WebCore { using namespace android; +class BaseLayerAndroid; +class LayerAndroid; + class TexturesGenerator : public Thread { public: TexturesGenerator() : Thread() @@ -46,6 +49,7 @@ public: virtual status_t readyToRun(); void removeOperationsForPage(TiledPage* page); + void removeOperationsForBaseLayer(BaseLayerAndroid* layer); void removeOperationsForFilter(OperationFilter* filter); void scheduleOperation(QueuedOperation* operation); diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 38dd282..3e174d1 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -30,6 +30,7 @@ #include "BaseTile.h" #include "SkCanvas.h" +#include "SkDevice.h" #include "SkPaint.h" #include <cutils/atomic.h> @@ -59,20 +60,27 @@ #define TILE_WIDTH 300 #define TILE_HEIGHT 300 +// Define a maximum amount of ram used by layers +#define MAX_LAYERS_ALLOCATION 20971520 // 20Mb +#define BYTES_PER_PIXEL 4 // 8888 config + namespace WebCore { TilesManager::TilesManager() - : m_generatorReady(false) + : m_layersMemoryUsage(0) + , m_generatorReady(false) { + XLOG("TilesManager ctor"); m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); for (int i = 0; i < MAX_TEXTURE_ALLOCATION; i++) { BackedDoubleBufferedTexture* texture = new BackedDoubleBufferedTexture( tileWidth(), tileHeight()); // the atomic load ensures that the texture has been fully initialized // before we pass a pointer for other threads to operate on - m_textures.append( - (BackedDoubleBufferedTexture*)android_atomic_acquire_load((int32_t*)&texture)); + m_textures.append(reinterpret_cast<BackedDoubleBufferedTexture*>( + android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)))); } + XLOG("TilesManager ctor"); m_pixmapsGenerationThread = new TexturesGenerator(); m_pixmapsGenerationThread->run("TexturesGenerator"); @@ -86,6 +94,7 @@ void TilesManager::enableTextures() BackedDoubleBufferedTexture* texture = m_textures[i]; texture->producerAcquireContext(); } + XLOG("enableTextures"); } void TilesManager::printTextures() @@ -217,6 +226,74 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner) return 0; } +LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer) +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i< m_layersTextures.size(); i++) { + if (m_layersTextures[i]->id() != layer->uniqueId()) + continue; + if (layer->getSize() != m_layersTextures[i]->getSize()) + continue; + + XLOG("return layer %d (%x) for tile %d (%x)", + i, m_layersTextures[i], + layer->uniqueId(), layer); + + if (m_layersTextures[i]->acquire(layer)) + return m_layersTextures[i]; + } + return 0; +} + +void TilesManager::printLayersTextures(const char* s) +{ +#ifdef DEBUG + for (unsigned int i = 0; i< m_layersTextures.size(); i++) { + XLOG("[%d] %s, texture %x for layer %d, owner: %x", i, s, m_layersTextures[i], + m_layersTextures[i]->id(), m_layersTextures[i]->owner()); + } +#endif +} + +void TilesManager::cleanupLayersTextures(bool forceCleanup) +{ + android::Mutex::Autolock lock(m_texturesLock); +#ifdef DEBUG + printLayersTextures("cleanup"); +#endif + for (unsigned int i = 0; i< m_layersTextures.size(); i++) { + LayerTexture* texture = m_layersTextures[i]; + + if (forceCleanup) + texture->setOwner(0); + + if (!texture->owner()) { + m_layersMemoryUsage -= (int) texture->getSize().fWidth + * (int) texture->getSize().fHeight * BYTES_PER_PIXEL; + m_layersTextures.remove(i); + delete texture; + } + } +} + +LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer) +{ + int w = layer->getWidth(); + int h = layer->getHeight(); + int size = w * h * BYTES_PER_PIXEL; + + if (m_layersMemoryUsage + size > MAX_LAYERS_ALLOCATION) + cleanupLayersTextures(true); + + android::Mutex::Autolock lock(m_texturesLock); + LayerTexture* texture = new LayerTexture(w, h); + texture->setId(layer->uniqueId()); + m_layersTextures.append(texture); + texture->acquire(layer); + m_layersMemoryUsage += size; + return texture; +} + int TilesManager::maxTextureCount() { return MAX_TEXTURE_ALLOCATION; diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index f855738..e69db4c 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -30,6 +30,8 @@ #include "BackedDoubleBufferedTexture.h" #include "BaseTile.h" +#include "LayerAndroid.h" +#include "LayerTexture.h" #include "ShaderProgram.h" #include "TexturesGenerator.h" #include "TiledPage.h" @@ -48,6 +50,11 @@ public: m_pixmapsGenerationThread->removeOperationsForPage(page); } + void removeOperationsForBaseLayer(BaseLayerAndroid* layer) + { + m_pixmapsGenerationThread->removeOperationsForBaseLayer(layer); + } + void scheduleOperation(QueuedOperation* operation) { m_pixmapsGenerationThread->scheduleOperation(operation); @@ -57,6 +64,11 @@ public: BackedDoubleBufferedTexture* getAvailableTexture(BaseTile* owner); + void printLayersTextures(const char* s); + void cleanupLayersTextures(bool forceCleanup = false); + LayerTexture* getExistingTextureForLayer(LayerAndroid* layer); + LayerTexture* createTextureForLayer(LayerAndroid* layer); + void markGeneratorAsReady() { android::Mutex::Autolock lock(m_generatorLock); @@ -84,6 +96,9 @@ private: } Vector<BackedDoubleBufferedTexture*> m_textures; + Vector<LayerTexture*> m_layersTextures; + + unsigned int m_layersMemoryUsage; bool m_generatorReady; |