summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/android
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/android')
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp10
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h6
-rw-r--r--WebCore/platform/graphics/android/BaseLayerAndroid.cpp30
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp14
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.h1
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp275
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h59
-rw-r--r--WebCore/platform/graphics/android/LayerTexture.cpp51
-rw-r--r--WebCore/platform/graphics/android/LayerTexture.h61
-rw-r--r--WebCore/platform/graphics/android/PaintLayerOperation.cpp61
-rw-r--r--WebCore/platform/graphics/android/PaintLayerOperation.h62
-rw-r--r--WebCore/platform/graphics/android/QueuedOperation.h12
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.cpp7
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.h4
-rw-r--r--WebCore/platform/graphics/android/TilesManager.cpp83
-rw-r--r--WebCore/platform/graphics/android/TilesManager.h15
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;