summaryrefslogtreecommitdiffstats
path: root/Source/WebCore
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2011-10-05 13:19:22 -0700
committerChris Craik <ccraik@google.com>2011-10-10 10:36:06 -0700
commite48d27773894f36d85e5c2e2052ab90d502e1c72 (patch)
tree9871a3729a937442be5fbd1af4dbf8e884fb3713 /Source/WebCore
parent63147313cabd16f95cd018f8b5ecc5070a985fe5 (diff)
downloadexternal_webkit-e48d27773894f36d85e5c2e2052ab90d502e1c72.zip
external_webkit-e48d27773894f36d85e5c2e2052ab90d502e1c72.tar.gz
external_webkit-e48d27773894f36d85e5c2e2052ab90d502e1c72.tar.bz2
Double buffering for layers
bug:5309934 Defer picture changes and invalidations when: 1) a tiled texture hasn't completed painting 2) the user is scrolling (done in PaintedSurface) Remaining issues: Should block updates on zooming Change-Id: I60ee722e651f96e95a4ac0e819999fc1589037c3
Diffstat (limited to 'Source/WebCore')
-rw-r--r--Source/WebCore/Android.mk1
-rw-r--r--Source/WebCore/platform/graphics/android/BaseRenderer.cpp2
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.cpp8
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.h1
-rw-r--r--Source/WebCore/platform/graphics/android/PaintedSurface.cpp65
-rw-r--r--Source/WebCore/platform/graphics/android/PaintedSurface.h16
-rw-r--r--Source/WebCore/platform/graphics/android/TilePainter.h2
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.h2
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.cpp109
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.h17
-rw-r--r--Source/WebCore/platform/graphics/android/UpdateManager.cpp120
-rw-r--r--Source/WebCore/platform/graphics/android/UpdateManager.h87
12 files changed, 328 insertions, 102 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 1250d91..5d1273b 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -678,6 +678,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/TiledPage.cpp \
platform/graphics/android/TiledTexture.cpp \
platform/graphics/android/TransferQueue.cpp \
+ platform/graphics/android/UpdateManager.cpp \
platform/graphics/android/VideoLayerAndroid.cpp \
platform/graphics/android/VideoLayerManager.cpp \
platform/graphics/android/ZoomManager.cpp \
diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp
index 68af1d6..96599af 100644
--- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp
@@ -132,7 +132,6 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo)
canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height());
canvas.scale(renderInfo.scale, renderInfo.scale);
unsigned int pictureCount = 0;
- renderInfo.tilePainter->beginPaint();
renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas, &pictureCount);
if (renderInfo.baseTile->isLayerTile())
renderInfo.tilePainter->paintExtra(&canvas);
@@ -161,7 +160,6 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo)
drawTileInfo(&canvas, renderInfo, pictureCount);
}
renderInfo.textureInfo->m_pictureCount = pictureCount;
- renderInfo.tilePainter->endPaint();
renderingComplete(renderInfo, &canvas);
return pictureCount;
}
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp
index 4a15f9f..318a969 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp
@@ -305,6 +305,14 @@ bool BaseTile::intersectWithRect(int x, int y, int tileWidth, int tileHeight,
return true;
}
+bool BaseTile::isTileVisible(const IntRect& viewTileBounds)
+{
+ return (m_x >= viewTileBounds.x()
+ && m_x < viewTileBounds.x() + viewTileBounds.width()
+ && m_y >= viewTileBounds.y()
+ && m_y < viewTileBounds.y() + viewTileBounds.height());
+}
+
// This is called from the texture generation thread
void BaseTile::paintBitmap()
{
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h
index 6d0fa8f..27fffc6 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.h
+++ b/Source/WebCore/platform/graphics/android/BaseTile.h
@@ -109,6 +109,7 @@ public:
bool intersectWithRect(int x, int y, int tileWidth, int tileHeight,
float scale, const SkRect& dirtyRect,
SkRect& realTileRect);
+ bool isTileVisible(const IntRect& viewTileBounds);
void markAsDirty(const unsigned int pictureCount,
const SkRegion& dirtyArea);
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
index 8a4c072..1eb51c7 100644
--- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
@@ -26,17 +26,21 @@
#include "config.h"
#include "PaintedSurface.h"
+
#include "LayerAndroid.h"
#include "TilesManager.h"
#include "SkCanvas.h"
#include "SkPicture.h"
-#ifdef DEBUG
-
#include <cutils/log.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__)
+
+#ifdef DEBUG
+
#undef XLOG
#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__)
@@ -60,12 +64,6 @@ PaintedSurface::~PaintedSurface()
delete m_tiledTexture;
}
-bool PaintedSurface::busy()
-{
- android::Mutex::Autolock lock(m_layerLock);
- return m_busy;
-}
-
void PaintedSurface::removeLayer()
{
android::Mutex::Autolock lock(m_layerLock);
@@ -96,6 +94,8 @@ void PaintedSurface::replaceLayer(LayerAndroid* layer)
SkSafeRef(layer);
SkSafeUnref(m_layer);
m_layer = layer;
+ if (layer && layer->picture())
+ m_updateManager.updatePicture(layer->picture());
}
void PaintedSurface::prepare(GLWebViewState* state)
@@ -106,6 +106,18 @@ void PaintedSurface::prepare(GLWebViewState* state)
if (!m_layer->needsTexture())
return;
+ bool startFastSwap = false;
+ if (state->isScrolling()) {
+ // when scrolling, block updates and swap tiles as soon as they're ready
+ startFastSwap = true;
+ } else {
+ // when not, push updates down to TiledTexture in every prepare
+ m_updateManager.swap();
+ m_tiledTexture->update(m_updateManager.getPaintingInval(),
+ m_updateManager.getPaintingPicture());
+ m_updateManager.clearPaintingInval();
+ }
+
XLOG("prepare layer %d %x at scale %.2f",
m_layer->uniqueId(), m_layer,
m_layer->getScale());
@@ -128,7 +140,7 @@ void PaintedSurface::prepare(GLWebViewState* state)
XLOG("layer %d %x prepared at size (%d, %d) @ scale %.2f", m_layer->uniqueId(),
m_layer, w, h, scale);
- m_tiledTexture->prepare(state, m_pictureUsed != m_layer->pictureUsed());
+ m_tiledTexture->prepare(state, m_pictureUsed != m_layer->pictureUsed(), startFastSwap);
}
bool PaintedSurface::draw()
@@ -139,44 +151,13 @@ bool PaintedSurface::draw()
bool askRedraw = false;
if (m_tiledTexture)
askRedraw = m_tiledTexture->draw();
- return askRedraw;
-}
-
-void PaintedSurface::beginPaint()
-{
- m_layerLock.lock();
- m_busy = true;
- m_layerLock.unlock();
-}
-void PaintedSurface::endPaint()
-{
- m_layerLock.lock();
- m_busy = false;
- m_layerLock.unlock();
+ return askRedraw;
}
void PaintedSurface::markAsDirty(const SkRegion& dirtyArea)
{
- m_tiledTexture->markAsDirty(dirtyArea);
-}
-
-bool PaintedSurface::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
-{
- m_layerLock.lock();
- LayerAndroid* layer = m_layer;
- SkSafeRef(layer);
- m_layerLock.unlock();
-
- if (!layer)
- return false;
-
- layer->contentDraw(canvas);
- m_pictureUsed = layer->pictureUsed();
- *pictureUsed = m_pictureUsed;
- SkSafeUnref(layer);
-
- return true;
+ m_updateManager.updateInval(dirtyArea);
}
void PaintedSurface::paintExtra(SkCanvas* canvas)
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h
index 88a9303..cda5960 100644
--- a/Source/WebCore/platform/graphics/android/PaintedSurface.h
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h
@@ -36,20 +36,22 @@
#include "TilesManager.h"
#include "TilePainter.h"
#include "TransformationMatrix.h"
+#include "UpdateManager.h"
class SkCanvas;
class SkRegion;
namespace WebCore {
-class PaintedSurface : public SkRefCnt, TilePainter {
+class UpdateManager;
+
+class PaintedSurface : public SkRefCnt {
public:
PaintedSurface(LayerAndroid* layer)
: m_layer(layer)
, m_tiledTexture(0)
, m_scale(0)
, m_pictureUsed(0)
- , m_busy(false)
{
TilesManager::instance()->addPaintedSurface(this);
SkSafeRef(m_layer);
@@ -70,18 +72,14 @@ public:
void removeLayer();
void removeLayer(LayerAndroid* layer);
void replaceLayer(LayerAndroid* layer);
- bool busy();
bool owns(BaseTileTexture* texture);
void computeVisibleArea();
- // TilePainter methods
- virtual bool paint(BaseTile*, SkCanvas*, unsigned int*);
+ // TilePainter methods for TiledTexture
virtual void paintExtra(SkCanvas*);
virtual const TransformationMatrix* transform();
- virtual void beginPaint();
- virtual void endPaint();
// used by TiledTexture
const IntRect& area() { return m_area; }
@@ -92,6 +90,8 @@ public:
TiledTexture* texture() { return m_tiledTexture; }
private:
+ UpdateManager m_updateManager;
+
LayerAndroid* m_layer;
TiledTexture* m_tiledTexture;
@@ -101,8 +101,6 @@ private:
unsigned int m_pictureUsed;
- bool m_busy;
-
android::Mutex m_layerLock;
};
diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h
index 31034e3..191edf3 100644
--- a/Source/WebCore/platform/graphics/android/TilePainter.h
+++ b/Source/WebCore/platform/graphics/android/TilePainter.h
@@ -40,8 +40,6 @@ public:
virtual bool paint(BaseTile* tile, SkCanvas*, unsigned int*) = 0;
virtual void paintExtra(SkCanvas*) = 0;
virtual const TransformationMatrix* transform() { return 0; }
- virtual void beginPaint() = 0;
- virtual void endPaint() = 0;
};
}
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h
index 780a604..718908d 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.h
+++ b/Source/WebCore/platform/graphics/android/TiledPage.h
@@ -84,8 +84,6 @@ public:
// used by individual tiles to generate the bitmap for their tile
bool paint(BaseTile*, SkCanvas*, unsigned int*);
void paintExtra(SkCanvas*);
- void beginPaint() {}
- void endPaint() {}
// used by individual tiles to get the information about the current picture
GLWebViewState* glWebViewState() { return m_glWebViewState; }
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
index c1fb4d1..8c63b42 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
@@ -33,12 +33,15 @@
#include "PaintTileOperation.h"
#include "SkCanvas.h"
-#ifdef DEBUG
-
#include <cutils/log.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/CString.h>
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
+
+#ifdef DEBUG
+
#undef XLOG
#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
@@ -51,7 +54,7 @@
namespace WebCore {
-void TiledTexture::prepare(GLWebViewState* state, bool repaint)
+void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSwap)
{
if (!m_surface)
return;
@@ -66,13 +69,6 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint)
ceilf(visibleArea.width() * m_surface->scale()),
ceilf(visibleArea.height() * m_surface->scale()));
- for (unsigned int i = 0; i < m_tiles.size(); i++) {
- BaseTile* tile = m_tiles[i];
- if (!m_dirtyRegion.isEmpty())
- tile->markAsDirty(1, m_dirtyRegion);
- }
- m_dirtyRegion.setEmpty();
-
if (area.width() == 0 && area.height() == 0) {
m_area.setWidth(0);
m_area.setHeight(0);
@@ -89,7 +85,7 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint)
m_area.setWidth(ceilf(right) - m_area.x());
m_area.setHeight(ceilf(bottom) - m_area.y());
- XLOG("for TiledTexture %x, we have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
+ XLOG("for TiledTexture %p, we have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
this,
visibleArea.x(), visibleArea.y(),
visibleArea.width(), visibleArea.height(),
@@ -104,6 +100,47 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint)
m_prevScale = m_surface->scale();
+ // unlock if tiles all ready
+ bool tilesAllReady = true;
+ for (unsigned int i = 0; i < m_tiles.size(); i++) {
+ BaseTile* tile = m_tiles[i];
+ if (tile->isTileVisible(m_area) && !tile->isTileReady()) {
+ tilesAllReady = false;
+ break;
+ }
+ }
+
+ // startFastSwap=true will swap all ready tiles each
+ // frame until all visible tiles are up to date
+ if (tilesAllReady)
+ m_swapWhateverIsReady = false;
+ else if (startFastSwap)
+ m_swapWhateverIsReady = true;
+
+ // swap as appropriate
+ for (unsigned int i = 0; i < m_tiles.size(); i++) {
+ BaseTile* tile = m_tiles[i];
+ if (tilesAllReady || m_swapWhateverIsReady)
+ tile->swapTexturesIfNeeded();
+ }
+
+ if (tilesAllReady) {
+ m_updateManager.swap();
+ m_dirtyRegion.op(m_updateManager.getPaintingInval(), SkRegion::kUnion_Op);
+ XLOG("TT %p swapping, now painting with picture %p"
+ this, m_updateManager.getPaintingPicture());
+ m_updateManager.clearPaintingInval();
+ }
+
+ // apply dirty region to affected tiles
+ if (!m_dirtyRegion.isEmpty()) {
+ for (unsigned int i = 0; i < m_tiles.size(); i++) {
+ // TODO: don't mark all tiles dirty
+ m_tiles[i]->markAsDirty(1, m_dirtyRegion);
+ }
+ }
+ m_dirtyRegion.setEmpty();
+
for (int i = 0; i < m_area.width(); i++) {
if (goingDown) {
for (int j = 0; j < m_area.height(); j++) {
@@ -117,9 +154,14 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint)
}
}
-void TiledTexture::markAsDirty(const SkRegion& dirtyArea)
+void TiledTexture::update(const SkRegion& invalRegion, SkPicture* picture)
{
- m_dirtyRegion.op(dirtyArea, SkRegion::kUnion_Op);
+ XLOG("TT %p, update manager %p updated with picture %p, region empty %d",
+ this, &m_updateManager, picture, invalRegion.isEmpty());
+ // attempt to update inval and picture. these may be deferred below instead
+ // of used immediately.
+ m_updateManager.updateInval(invalRegion);
+ m_updateManager.updatePicture(picture);
}
void TiledTexture::prepareTile(bool repaint, int x, int y)
@@ -130,6 +172,7 @@ void TiledTexture::prepareTile(bool repaint, int x, int y)
m_tiles.append(tile);
}
+ XLOG("preparing tile %p, painter is this %p", tile, this);
tile->setContents(this, x, y, m_surface->scale());
// TODO: move below (which is largely the same for layers / tiled page) into
@@ -160,9 +203,8 @@ bool TiledTexture::draw()
TilesManager::instance()->getTilesTracker()->trackLayer();
#endif
- bool askRedraw = false;
if (m_area.width() == 0 || m_area.height() == 0)
- return askRedraw;
+ return false;
#ifdef DEBUG
TilesManager::instance()->getTilesTracker()->trackVisibleLayer();
@@ -172,38 +214,35 @@ bool TiledTexture::draw()
const float tileWidth = TilesManager::layerTileWidth() * m_invScale;
const float tileHeight = TilesManager::layerTileHeight() * m_invScale;
XLOG("draw tile %x, tiles %d", this, m_tiles.size());
- for (unsigned int i = 0; i <m_tiles.size(); i++) {
+
+ bool askRedraw = false;
+ for (unsigned int i = 0; i < m_tiles.size(); i++) {
BaseTile* tile = m_tiles[i];
- if (tile->x() >= m_area.x()
- && tile->x() < m_area.x() + m_area.width()
- && tile->y() >= m_area.y()
- && tile->y() < m_area.y() + m_area.height()) {
+
+ askRedraw |= !tile->isTileReady();
+ if (tile->isTileVisible(m_area)) {
SkRect rect;
rect.fLeft = tile->x() * tileWidth;
rect.fTop = tile->y() * tileHeight;
rect.fRight = rect.fLeft + tileWidth;
rect.fBottom = rect.fTop + tileHeight;
XLOG(" - [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f [ready: %d] dirty: %d",
- i, this, tile->painter(), tile, tile->x(), tile->y(), tile->scale(), tile->isTileReady(), tile->isDirty());
- askRedraw |= !tile->isTileReady();
- tile->swapTexturesIfNeeded();
+ i, this, tile->painter(), tile, tile->x(), tile->y(),
+ tile->scale(), tile->isTileReady(), tile->isDirty());
tile->draw(m_surface->opacity(), rect, m_surface->scale());
#ifdef DEBUG
TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
#endif
}
}
+
+ // need to redraw if some visible tile wasn't ready
return askRedraw;
}
bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
{
- if (!m_surface)
- return false;
-
- XLOG("painting scheduled tile(%x : %d, %d, %.2f, %x) for %x",
- tile, tile->x(), tile->y(), tile->scale(), tile->painter(), this);
- return m_surface->paint(tile, canvas, pictureUsed);
+ return m_updateManager.paint(tile, canvas, pictureUsed);
}
void TiledTexture::paintExtra(SkCanvas* canvas)
@@ -216,18 +255,6 @@ const TransformationMatrix* TiledTexture::transform()
return m_surface->transform();
}
-void TiledTexture::beginPaint()
-{
- if (m_surface)
- m_surface->beginPaint();
-}
-
-void TiledTexture::endPaint()
-{
- if (m_surface)
- m_surface->endPaint();
-}
-
void TiledTexture::removeTiles()
{
for (unsigned int i = 0; i < m_tiles.size(); i++) {
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h
index 6ebfc05..aa82e36 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.h
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.h
@@ -34,11 +34,13 @@
#include "SkRegion.h"
#include "TextureOwner.h"
#include "TilePainter.h"
+#include "UpdateManager.h"
class SkCanvas;
namespace WebCore {
+class UpdateManager;
class PaintedSurface;
class TiledTexture : public TilePainter {
@@ -48,6 +50,7 @@ public:
, m_prevTileX(0)
, m_prevTileY(0)
, m_prevScale(1)
+ , m_swapWhateverIsReady(false)
{
m_dirtyRegion.setEmpty();
#ifdef DEBUG_COUNT
@@ -62,11 +65,11 @@ public:
removeTiles();
};
- void prepare(GLWebViewState* state, bool repaint);
+ void prepare(GLWebViewState* state, bool repaint, bool startFastSwap);
bool draw();
void prepareTile(bool repaint, int x, int y);
- void markAsDirty(const SkRegion& dirtyArea);
+ void update(const SkRegion& dirtyArea, SkPicture* picture);
BaseTile* getTile(int x, int y);
@@ -77,19 +80,25 @@ public:
bool paint(BaseTile* tile, SkCanvas*, unsigned int*);
virtual void paintExtra(SkCanvas*);
virtual const TransformationMatrix* transform();
- virtual void beginPaint();
- virtual void endPaint();
private:
+ bool tileIsVisible(BaseTile* tile);
+
+ UpdateManager m_updateManager;
+
PaintedSurface* m_surface;
Vector<BaseTile*> m_tiles;
+ // tile coordinates in viewport, set in prepare()
IntRect m_area;
+
SkRegion m_dirtyRegion;
int m_prevTileX;
int m_prevTileY;
float m_prevScale;
+
+ bool m_swapWhateverIsReady;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/UpdateManager.cpp b/Source/WebCore/platform/graphics/android/UpdateManager.cpp
new file mode 100644
index 0000000..1c20f1f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/UpdateManager.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011, 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 "PaintedSurface.h"
+
+#include "LayerAndroid.h"
+#include "TilesManager.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "UpdateManager", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "UpdateManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+UpdateManager::UpdateManager()
+ : m_paintingPicture(0)
+ , m_deferredPicture(0)
+{
+}
+
+UpdateManager::~UpdateManager()
+{
+ SkSafeUnref(m_paintingPicture);
+ SkSafeUnref(m_deferredPicture);
+}
+
+void UpdateManager::swap()
+{
+ m_paintingInval.op(m_deferredInval, SkRegion::kUnion_Op);
+ m_deferredInval.setEmpty();
+
+ android::Mutex::Autolock lock(m_paintingPictureSync);
+ if (m_deferredPicture) {
+ XLOG("unlock of updatemanager %p, was painting %p, now painting %p",
+ this, m_paintingPicture, m_deferredPicture);
+ SkSafeUnref(m_paintingPicture);
+ m_paintingPicture = m_deferredPicture;
+ m_deferredPicture = 0;
+ }
+}
+
+void UpdateManager::updateInval(const SkRegion& invalRegion)
+{
+ m_deferredInval.op(invalRegion, SkRegion::kUnion_Op);
+}
+
+void UpdateManager::updatePicture(SkPicture* picture)
+{
+ SkSafeRef(picture);
+ SkSafeUnref(m_deferredPicture);
+ m_deferredPicture = picture;
+}
+
+bool UpdateManager::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
+{
+ m_paintingPictureSync.lock();
+ SkPicture* picture = m_paintingPicture;
+ SkSafeRef(picture);
+ m_paintingPictureSync.unlock();
+
+ XLOG("UpdateManager %p painting with picture %p", this, picture);
+
+ if (!picture)
+ return false;
+
+ canvas->drawPicture(*picture);
+
+ // TODO: visualization layer diagonals
+
+ SkSafeUnref(picture);
+ return true;
+}
+
+
+void UpdateManager::clearPaintingInval()
+{
+ m_paintingInval.setEmpty();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/UpdateManager.h b/Source/WebCore/platform/graphics/android/UpdateManager.h
new file mode 100644
index 0000000..6254184
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/UpdateManager.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2011, 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 UpdateManager_h
+#define UpdateManager_h
+
+class SkCanvas;
+class SkRegion;
+
+namespace WebCore {
+
+class BaseTile;
+
+// UpdateManager Architecture
+
+// The UpdateManager is used to defer updates and invalidations to a layer,
+// so that the layer can finish painting one version completely without being
+// interrupted by new invals/content
+
+class UpdateManager {
+public:
+ UpdateManager();
+
+ ~UpdateManager();
+
+ // swap deferred members in place of painting members
+ void swap();
+
+ void updateInval(const SkRegion& invalRegion);
+
+ void updatePicture(SkPicture* picture);
+
+ bool paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed);
+
+ void clearPaintingInval();
+
+ const SkRegion& getPaintingInval() {
+ return m_paintingInval;
+ }
+
+ SkPicture* getPaintingPicture() {
+ // NOTE: only modified on UI thread, so UI thread access doesn't need mutex
+ return m_paintingPicture;
+ }
+
+private:
+ // protect m_paintingPicture
+ // swap() on UI thread modifies
+ // paint() on texture gen thread reads
+ android::Mutex m_paintingPictureSync;
+ SkPicture* m_paintingPicture;
+
+ // inval region to be redrawn with the current paintingPicture
+ SkRegion m_paintingInval;
+
+ // most recently received picture, moved into painting on swap()
+ SkPicture* m_deferredPicture;
+
+ // all invals since last swap(), merged with painting inval on swap()
+ SkRegion m_deferredInval;
+};
+
+} // namespace WebCore
+
+#endif //#define UpdateManager_h