summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp38
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h55
-rw-r--r--WebCore/platform/graphics/android/BaseTile.cpp103
-rw-r--r--WebCore/platform/graphics/android/BaseTile.h24
-rw-r--r--WebCore/platform/graphics/android/DoubleBufferedTexture.h5
-rw-r--r--WebCore/platform/graphics/android/GLWebViewState.cpp11
-rw-r--r--WebCore/platform/graphics/android/GLWebViewState.h27
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.cpp11
-rw-r--r--WebCore/platform/graphics/android/TileSet.cpp32
-rw-r--r--WebCore/platform/graphics/android/TileSet.h11
-rw-r--r--WebCore/platform/graphics/android/TiledPage.cpp67
-rw-r--r--WebCore/platform/graphics/android/TiledPage.h15
-rw-r--r--WebCore/platform/graphics/android/TilesManager.cpp5
13 files changed, 199 insertions, 205 deletions
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
index 7cecddd..1a8e686 100644
--- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
+++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
@@ -56,28 +56,27 @@ BackedDoubleBufferedTexture::~BackedDoubleBufferedTexture()
TextureInfo* BackedDoubleBufferedTexture::producerLock()
{
- m_varLock.lock();
+ m_busyLock.lock();
m_busy = true;
- m_varLock.unlock();
+ m_busyLock.unlock();
return DoubleBufferedTexture::producerLock();
}
void BackedDoubleBufferedTexture::producerRelease()
{
DoubleBufferedTexture::producerRelease();
- android::Mutex::Autolock lock(m_varLock);
+ android::Mutex::Autolock lock(m_busyLock);
m_busy = false;
}
void BackedDoubleBufferedTexture::producerReleaseAndSwap()
{
DoubleBufferedTexture::producerReleaseAndSwap();
- android::Mutex::Autolock lock(m_varLock);
+ android::Mutex::Autolock lock(m_busyLock);
m_busy = false;
}
-void BackedDoubleBufferedTexture::producerUpdate(BaseTile* painter,
- TextureInfo* textureInfo, PaintingInfo& info)
+void BackedDoubleBufferedTexture::producerUpdate(TextureInfo* textureInfo)
{
// no need to upload a texture since the bitmap is empty
if (!m_bitmap.width() && !m_bitmap.height()) {
@@ -93,34 +92,9 @@ void BackedDoubleBufferedTexture::producerUpdate(BaseTile* painter,
textureInfo->m_height = m_bitmap.height();
}
- m_varLock.lock();
- // set the painting information for this texture
- if (equalsIdTextureA(textureInfo->m_textureId))
- m_paintingInfoA = info;
- else if (equalsIdTextureB(textureInfo->m_textureId))
- m_paintingInfoB = info;
- m_varLock.unlock();
-
producerReleaseAndSwap();
}
-// Compare the current texture displayed with some PaintingInfo.
-bool BackedDoubleBufferedTexture::consumerTextureUpToDate(PaintingInfo& info)
-{
- android::Mutex::Autolock lock(m_varLock);
- if (isTextureAReadable())
- return info == m_paintingInfoA;
- return info == m_paintingInfoB;
-}
-
-bool BackedDoubleBufferedTexture::consumerTextureSimilar(PaintingInfo& info)
-{
- android::Mutex::Autolock lock(m_varLock);
- if (isTextureAReadable())
- return info.similar(m_paintingInfoA);
- return info.similar(m_paintingInfoB);
-}
-
bool BackedDoubleBufferedTexture::acquire(BaseTile* owner)
{
if (m_owner == owner)
@@ -128,7 +102,7 @@ bool BackedDoubleBufferedTexture::acquire(BaseTile* 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_varLock);
+ android::Mutex::Autolock lock(m_busyLock);
if (!m_busy) {
if (m_owner)
m_owner->removeTexture();
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h
index 1faa110..6bbb97a 100644
--- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h
+++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h
@@ -36,42 +36,6 @@ namespace WebCore {
class BaseTile;
-class PaintingInfo {
-public:
- PaintingInfo() : m_x(-1), m_y(-1), m_webview(0), m_picture(0) { }
- PaintingInfo(int x, int y, GLWebViewState* webview)
- : m_x(x)
- , m_y(y)
- , m_webview(webview)
- , m_picture(0)
- {
- if(webview)
- m_picture = webview->currentPictureCounter();
- }
- bool operator==(const PaintingInfo& info)
- {
- return m_webview == info.m_webview
- && m_x == info.m_x
- && m_y == info.m_y
- && m_picture == info.m_picture;
- }
- bool similar(const PaintingInfo& info)
- {
- return m_webview == info.m_webview
- && m_x == info.m_x
- && m_y == info.m_y;
- }
- void setPosition(int x, int y) { m_x = x; m_y = y; }
- void setGLWebViewState(GLWebViewState* webview) { m_webview = webview; }
- void setPictureUsed(unsigned int picture) { m_picture = picture; }
-
-private:
- int m_x;
- int m_y;
- GLWebViewState* m_webview;
- unsigned int m_picture;
-};
-
// DoubleBufferedTexture using a SkBitmap as backing mechanism
class BackedDoubleBufferedTexture : public DoubleBufferedTexture {
public:
@@ -88,7 +52,7 @@ public:
// updates the texture with current bitmap and releases (and if needed also
// swaps) the texture.
- void producerUpdate(BaseTile* painter, TextureInfo* textureInfo, PaintingInfo& info);
+ void producerUpdate(TextureInfo* textureInfo);
// The level can be one of the following values:
// * -1 for an unused texture.
@@ -107,11 +71,7 @@ public:
BaseTile* owner() { return m_owner; } // only used by the consumer thread
SkCanvas* canvas() { return m_canvas; } // only used by the producer thread
- // checks to see if the current readable texture equals the provided PaintingInfo
- bool consumerTextureUpToDate(PaintingInfo& info);
- // checks to see if the current readable texture is similar to the provided PaintingInfo
- bool consumerTextureSimilar(PaintingInfo& info);
-
+ // This is to be only used for debugging on the producer thread
bool busy() { return m_busy; }
private:
@@ -120,12 +80,13 @@ private:
int m_usedLevel;
BaseTile* m_owner;
- //The following values are shared among threads and use m_varLock to stay synced
- PaintingInfo m_paintingInfoA;
- PaintingInfo m_paintingInfoB;
+ // This values signals that the texture is currently in use by the consumer.
+ // This allows us to prevent the owner of the texture from changing while the
+ // consumer is holding a lock on the texture.
bool m_busy;
-
- android::Mutex m_varLock;
+ // We mutex protect the reads/writes of m_busy to ensure that we are reading
+ // the most up-to-date value even across processors in an SMP system.
+ android::Mutex m_busyLock;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp
index 5ab801e..1c81634 100644
--- a/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/WebCore/platform/graphics/android/BaseTile.cpp
@@ -72,6 +72,9 @@ BaseTile::BaseTile(TiledPage* page, int x, int y)
, m_y(y)
, m_texture(0)
, m_scale(1)
+ , m_dirty(true)
+ , m_lastDirtyPicture(0)
+ , m_lastPaintedPicture(0)
{
#ifdef DEBUG_COUNT
gBaseTileCount++;
@@ -80,6 +83,7 @@ BaseTile::BaseTile(TiledPage* page, int x, int y)
BaseTile::~BaseTile()
{
+ setUsedLevel(-1);
#ifdef DEBUG_COUNT
gBaseTileCount--;
#endif
@@ -90,26 +94,43 @@ BaseTile::~BaseTile()
void BaseTile::reserveTexture()
{
BackedDoubleBufferedTexture* texture = TilesManager::instance()->getAvailableTexture(this);
- // We update atomically, so paintBitmap() can see the correct value
- android_atomic_acquire_store((int32_t)texture, (int32_t*)&m_texture);
- XLOG("%x (%d, %d) reserveTexture res: %x...", this, x(), y(), m_texture);
+
+ android::AutoMutex lock(m_atomicSync);
+ if (m_texture != texture) {
+ m_lastPaintedPicture = 0;
+ m_dirty = true;
+ }
+ m_texture = texture;
}
void BaseTile::removeTexture()
{
XLOG("%x removeTexture res: %x...", this, m_texture);
// We update atomically, so paintBitmap() can see the correct value
- android_atomic_acquire_store(0, (int32_t*)&m_texture);
+ android::AutoMutex lock(m_atomicSync);
+ m_texture = 0;
}
void BaseTile::setScale(float scale)
{
+ android::AutoMutex lock(m_atomicSync);
+ if (m_scale != scale)
+ m_dirty = true;
m_scale = scale;
- // FIXME: the following two lines force a memory barrier which causes
- // m_scale to be observable on other cores. We should replace this
- // with a dedicated system function if/when available.
- int32_t tempValue = 0;
- android_atomic_acquire_load(&tempValue);
+}
+
+void BaseTile::markAsDirty(int pictureCount)
+{
+ android::AutoMutex lock(m_atomicSync);
+ m_lastDirtyPicture = pictureCount;
+ if (m_lastPaintedPicture < m_lastDirtyPicture)
+ m_dirty = true;
+}
+
+bool BaseTile::isDirty()
+{
+ android::AutoMutex lock(m_atomicSync);
+ return m_dirty;
}
void BaseTile::setUsedLevel(int usedLevel)
@@ -120,13 +141,13 @@ void BaseTile::setUsedLevel(int usedLevel)
void BaseTile::draw(float transparency, SkRect& rect)
{
+ // No need to mutex protect reads of m_texture as it is only written to by
+ // the consumer thread.
if (!m_texture) {
XLOG("%x (%d, %d) trying to draw, but no m_texture!", this, x(), y());
return;
}
- PaintingInfo info(m_x, m_y, m_page->glWebViewState());
-
TextureInfo* textureInfo = m_texture->consumerLock();
if (!textureInfo) {
XLOG("%x (%d, %d) trying to draw, but no textureInfo!", this, x(), y());
@@ -134,61 +155,57 @@ void BaseTile::draw(float transparency, SkRect& rect)
return;
}
- if (m_texture->consumerTextureSimilar(info)) {
+ m_atomicSync.lock();
+ bool isTexturePainted = m_lastPaintedPicture;
+ m_atomicSync.unlock();
+
+ if (isTexturePainted)
TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId,
transparency);
- }
m_texture->consumerRelease();
}
-bool BaseTile::isBitmapReady()
+bool BaseTile::isTileReady()
{
if (!m_texture)
return false;
if (m_texture->owner() != this)
return false;
- PaintingInfo info(m_x, m_y, m_page->glWebViewState());
- return m_texture->consumerTextureUpToDate(info);
+
+ android::AutoMutex lock(m_atomicSync);
+ return !m_dirty;
}
// This is called from the texture generation thread
void BaseTile::paintBitmap()
{
- const int x = m_x;
- const int y = m_y;
- TiledPage* tiledPage = m_page;
-
- // We acquire the texture atomically. Once we have it, we
- // can continue with it, and m_texture can be updated without
- // consequences.
- BackedDoubleBufferedTexture* texture = reinterpret_cast<BackedDoubleBufferedTexture*>(
- android_atomic_release_load((int32_t*)&m_texture));
- // The loading of m_texture forces the execution of a memory barrier,
- // which ensures that we are observing the most recent value of m_scale
- // written by another core.
+ // 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();
+ bool dirty = m_dirty;
+ BackedDoubleBufferedTexture* texture = m_texture;
float scale = m_scale;
+ m_atomicSync.unlock();
- if (!texture)
+ if(!dirty || !texture)
return;
+ const int x = m_x;
+ const int y = m_y;
+ TiledPage* tiledPage = m_page;
+
TextureInfo* textureInfo = texture->producerLock();
- // at this point we can safely check the ownership
- // (if the texture got transferred to another BaseTile
- // under us)
+ // at this point we can safely check the ownership (if the texture got
+ // transferred to another BaseTile under us)
if (texture->owner() != this || texture->usedLevel() > 1) {
texture->producerRelease();
return;
}
- PaintingInfo info(x, y, tiledPage->glWebViewState());
- if (texture->consumerTextureUpToDate(info)) {
- texture->producerRelease();
- return;
- }
-
float tileWidth = textureInfo->m_width;
float tileHeight = textureInfo->m_height;
@@ -203,7 +220,7 @@ void BaseTile::paintBitmap()
canvas->scale(scale, scale);
canvas->translate(-x * w, -y * h);
- tiledPage->paintBaseLayerContent(canvas);
+ int pictureCount = tiledPage->paintBaseLayerContent(canvas);
canvas->restore();
@@ -219,7 +236,13 @@ void BaseTile::paintBitmap()
canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint);
#endif
- texture->producerUpdate(this, textureInfo, info);
+ texture->producerUpdate(textureInfo);
+
+ m_atomicSync.lock();
+ m_lastPaintedPicture = pictureCount;
+ if (m_lastPaintedPicture >= m_lastDirtyPicture)
+ m_dirty = false;
+ m_atomicSync.unlock();
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h
index 429d950..896edb3 100644
--- a/WebCore/platform/graphics/android/BaseTile.h
+++ b/WebCore/platform/graphics/android/BaseTile.h
@@ -36,6 +36,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
+#include <utils/threads.h>
namespace WebCore {
@@ -69,12 +70,15 @@ public:
void reserveTexture();
void removeTexture();
void setUsedLevel(int);
- bool isBitmapReady();
+ bool isTileReady();
void draw(float transparency, SkRect& rect);
// the only thread-safe function called by the background thread
void paintBitmap();
+ void markAsDirty(int pictureCount);
+ bool isDirty();
+
float scale() const { return m_scale; }
void setScale(float scale);
@@ -89,9 +93,25 @@ private:
int m_x;
int m_y;
- // these variables can be updated throughout the lifetime of the object
+ // The remaining variables can be updated throughout the lifetime of the object
BackedDoubleBufferedTexture* m_texture;
float m_scale;
+ // used to signal that the that the tile is out-of-date and needs to be redrawn
+ bool m_dirty;
+ // stores the id of the latest picture from webkit that caused this tile to
+ // become dirty. A tile is no longer dirty when it has been painted with a
+ // picture that is newer than this value.
+ int m_lastDirtyPicture;
+ // stores the id of the latest picture painted to the tile. If the id is 0
+ // then we know that the picture has not yet been painted an there is nothing
+ // to display (dirty or otherwise).
+ int m_lastPaintedPicture;
+
+ // 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;
+
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/WebCore/platform/graphics/android/DoubleBufferedTexture.h
index d16d5f3..2b2fd03 100644
--- a/WebCore/platform/graphics/android/DoubleBufferedTexture.h
+++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.h
@@ -50,11 +50,6 @@ public:
TextureInfo* consumerLock();
void consumerRelease();
-protected:
- bool equalsIdTextureA(GLuint id) { return id == m_textureA.getSourceTextureId(); }
- bool equalsIdTextureB(GLuint id) { return id == m_textureB.getSourceTextureId(); }
- bool isTextureAReadable() { return getReadableTexture() == &m_textureA; }
-
private:
SharedTexture* getReadableTexture();
SharedTexture* getWriteableTexture();
diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp
index e1e517c..814e590 100644
--- a/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -81,7 +81,6 @@ GLWebViewState::GLWebViewState()
, m_extra(0)
, m_navLayer(0)
{
- m_invalidatedRect.setEmpty();
m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this);
m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this);
#ifdef DEBUG_COUNT
@@ -108,8 +107,13 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, IntRect& rect)
m_navLayer = 0;
if (m_baseLayer) {
m_baseLayer->setGLWebViewState(this);
- m_invalidatedRect.set(rect);
m_currentPictureCounter++;
+
+ if (!rect.isEmpty()) {
+ // find which tiles fall within the invalRect and mark them as dirty
+ m_tiledPageA->invalidateRect(rect, m_currentPictureCounter);
+ m_tiledPageB->invalidateRect(rect, m_currentPictureCounter);
+ }
}
}
@@ -132,7 +136,7 @@ void GLWebViewState::resetExtra(bool repaint)
m_navLayer = 0;
}
-void GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
+int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
{
android::Mutex::Autolock lock(m_baseLayerLock);
if (m_baseLayer) {
@@ -140,6 +144,7 @@ void GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
if (m_extra && m_navLayer)
m_extra->draw(canvas, m_navLayer);
}
+ return m_currentPictureCounter;
}
void GLWebViewState::scheduleUpdate(const double& currentTime, float scale)
diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h
index 95bc07d..04dea6d 100644
--- a/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/WebCore/platform/graphics/android/GLWebViewState.h
@@ -95,8 +95,9 @@ class LayerAndroid;
// get the GL textures from an existing pool, and reuse them.
//
// The way we do it is that when we call TiledPage::prepare(), we group the
-// tiles we need into a TilesSet, call TilesSet::reserveTextures() (which
-// associates the GL textures to the BaseTiles).
+// tiles we need (i.e. in the viewport and dirty) into a TilesSet and call
+// BaseTile::reserveTexture() for each tile (which ensures there is a specific
+// GL textures backing the BaseTiles).
//
// reserveTexture() will ask the TilesManager for a texture. The allocation
// mechanism goal is to (in order):
@@ -104,8 +105,22 @@ class LayerAndroid;
// - prefers to allocate textures that are as far from the viewport as possible
// - prefers to allocate textures that are used by different TiledPages
//
-// Note that to compute the distance of tiles, each time we prepare() a
-// TiledPage, we compute the distance of the tiles in it from the viewport.
+// Note that to compute the distance of each tile from the viewport, each time
+// we prepare() a TiledPage. Also during each prepare() we compute which tiles
+// are dirty based on the info we have received from webkit.
+//
+// BaseTile Invalidation
+// ------------------
+//
+// We do not want to redraw a tile if the tile is up-to-date. A tile is
+// considered to be dirty an in need of redrawing in the following cases
+// - the tile has acquires a new texture
+// - webkit invalidates all or part of the tiles contents
+//
+// To handle the case of webkit invalidation we store two ids (counters) of the
+// pictureSets in the tile. The first id (A) represents the pictureSet used to
+// paint the tile and the second id (B) represents the pictureSet in which the
+// tile was invalidated by webkit. Thus, if A < B then tile is dirty.
//
// Painting scheduling
// -------------------
@@ -155,7 +170,7 @@ public:
int originalTilesPosY() const { return m_originalTilesPosY; }
void setOriginalTilesPosY(int pos) { m_originalTilesPosY = pos; }
- void paintBaseLayerContent(SkCanvas* canvas);
+ int paintBaseLayerContent(SkCanvas* canvas);
void setBaseLayer(BaseLayerAndroid* layer, IntRect& rect);
void setExtra(android::DrawExtra* extra, LayerAndroid* navLayer);
void resetExtra(bool repaint);
@@ -176,7 +191,6 @@ public:
int firstTileY() const { return m_firstTileY; }
unsigned int currentPictureCounter() const { return m_currentPictureCounter; }
- SkRect& invalidatedRect() { return m_invalidatedRect; }
private:
@@ -207,7 +221,6 @@ private:
android::Mutex m_baseLayerLock;
BaseLayerAndroid* m_baseLayer;
unsigned int m_currentPictureCounter;
- SkRect m_invalidatedRect;
bool m_usePageA;
TiledPage* m_tiledPageA;
TiledPage* m_tiledPageB;
diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp
index f81a297..193ca46 100644
--- a/WebCore/platform/graphics/android/TexturesGenerator.cpp
+++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp
@@ -53,10 +53,13 @@ void TexturesGenerator::schedulePaintForTileSet(TileSet* set)
{
android::Mutex::Autolock lock(mRequestedPixmapsLock);
for (unsigned int i = 0; i < mRequestedPixmaps.size(); i++) {
- TileSet* s = mRequestedPixmaps[i];
- if (s && *s == *set) {
- // Similar set already in the queue
- delete set;
+ TileSet** s = &mRequestedPixmaps[i];
+ // A similar set is already in the queue. The newer set may have additional
+ // dirty tiles so delete the existing set and replace it with the new one.
+ if (*s && **s == *set) {
+ TileSet* oldSet = *s;
+ *s = set;
+ delete oldSet;
return;
}
}
diff --git a/WebCore/platform/graphics/android/TileSet.cpp b/WebCore/platform/graphics/android/TileSet.cpp
index fe13ef3..4530640 100644
--- a/WebCore/platform/graphics/android/TileSet.cpp
+++ b/WebCore/platform/graphics/android/TileSet.cpp
@@ -56,10 +56,8 @@ int TileSet::count()
}
#endif
-TileSet::TileSet(int id, int firstTileX, int firstTileY, int rows, int cols)
- : m_id(id)
- , m_firstTileX(firstTileX)
- , m_firstTileY(firstTileY)
+TileSet::TileSet(TiledPage* tiledPage, int rows, int cols)
+ : m_tiledPage(tiledPage)
, m_nbRows(rows)
, m_nbCols(cols)
{
@@ -77,36 +75,12 @@ TileSet::~TileSet()
bool TileSet::operator==(const TileSet& set)
{
- return m_id == set.m_id
- && m_firstTileX == set.m_firstTileX
- && m_firstTileY == set.m_firstTileY
+ return m_tiledPage == set.m_tiledPage
&& m_nbRows == set.m_nbRows
&& m_nbCols == set.m_nbCols;
}
-void TileSet::reserveTextures()
-{
-#ifdef DEBUG
- if (m_tiles.size()) {
- TiledPage* page = m_tiles[0]->page();
- XLOG("reserveTextures (%d tiles) for page %x (sibling: %x)", m_tiles.size(), page, page->sibling());
- TilesManager::instance()->printTextures();
- }
-#endif // DEBUG
-
- for (unsigned int i = 0; i < m_tiles.size(); i++)
- m_tiles[i]->reserveTexture();
-
-#ifdef DEBUG
- if (m_tiles.size()) {
- TiledPage* page = m_tiles[0]->page();
- XLOG(" DONE reserveTextures (%d tiles) for page %x (sibling: %x)", m_tiles.size(), page, page->sibling());
- TilesManager::instance()->printTextures();
- }
-#endif // DEBUG
-}
-
void TileSet::paint()
{
XLOG("%x, painting %d tiles", this, m_tiles.size());
diff --git a/WebCore/platform/graphics/android/TileSet.h b/WebCore/platform/graphics/android/TileSet.h
index adf6d13..fd65ad7 100644
--- a/WebCore/platform/graphics/android/TileSet.h
+++ b/WebCore/platform/graphics/android/TileSet.h
@@ -45,11 +45,10 @@ public:
#ifdef DEBUG_COUNT
static int count();
#endif
- TileSet(int id, int firstTileX, int firstTileY, int rows, int cols);
+ TileSet(TiledPage* tiledPage, int nbRows, int nbCols);
~TileSet();
bool operator==(const TileSet& set);
- void reserveTextures();
void paint();
void add(BaseTile* texture)
@@ -59,17 +58,13 @@ public:
TiledPage* page()
{
- if (m_tiles.size())
- return m_tiles[0]->page();
- return 0;
+ return m_tiledPage;
}
private:
Vector<BaseTile*> m_tiles;
- int m_id;
- int m_firstTileX;
- int m_firstTileY;
+ TiledPage* m_tiledPage;
int m_nbRows;
int m_nbCols;
};
diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp
index 6430b02..6b11c52 100644
--- a/WebCore/platform/graphics/android/TiledPage.cpp
+++ b/WebCore/platform/graphics/android/TiledPage.cpp
@@ -29,6 +29,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "GLUtils.h"
+#include "IntRect.h"
#include "TilesManager.h"
#ifdef DEBUG
@@ -64,6 +65,7 @@ TiledPage::TiledPage(int id, GLWebViewState* state)
, m_scale(1)
, m_invScale(1)
, m_glWebViewState(state)
+ , m_latestPictureInval(0)
{
#ifdef DEBUG_COUNT
gTilePageCount++;
@@ -94,6 +96,24 @@ BaseTile* TiledPage::getBaseTile(int x, int y)
return m_baseTiles.get(key);
}
+void TiledPage::invalidateRect(const IntRect& inval, const int pictureCount)
+{
+ // Given the current scale level we need to mark the appropriate tiles as dirty
+ TilesManager* manager = TilesManager::instance();
+ const float invTileContentWidth = m_scale / manager->tileWidth();
+ const float invTileContentHeight = m_scale / manager->tileHeight();
+
+ const int firstDirtyTileX = static_cast<int>(floorf(inval.x() * invTileContentWidth));
+ const int firstDirtyTileY = static_cast<int>(floorf(inval.y() * invTileContentHeight));
+ const int lastDirtyTileX = static_cast<int>(ceilf(inval.right() * invTileContentWidth));
+ const int lastDirtyTileY = static_cast<int>(ceilf(inval.bottom() * invTileContentHeight));
+
+ // We defer marking the tile as dirty until the next time we need to prepare
+ // to draw.
+ m_invalRegion.op(firstDirtyTileX, firstDirtyTileY, lastDirtyTileX, lastDirtyTileY, SkRegion::kUnion_Op);
+ m_latestPictureInval = pictureCount;
+}
+
void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set)
{
if (y < 0)
@@ -119,11 +139,16 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y
}
tile = m_baseTiles.get(key);
tile->setScale(m_scale);
- set->add(tile);
+
+ // ensure there is a texture associated with the tile and then check to
+ // see if the texture is dirty and in need of repainting
+ tile->reserveTexture();
+ if(tile->isDirty())
+ set->add(tile);
}
}
-void TiledPage::setTileLevels(int firstTileX, int firstTileY)
+void TiledPage::updateTileState(int firstTileX, int firstTileY)
{
if (!m_glWebViewState)
return;
@@ -138,6 +163,11 @@ void TiledPage::setTileLevels(int firstTileX, int firstTileY)
if(!tile)
continue;
+ // if the tile is in the dirty region then we must invalidate it
+ if (m_invalRegion.contains(tile->x(), tile->y()))
+ tile->markAsDirty(m_latestPictureInval);
+
+ // set the used level of the tile (e.g. distance from the viewport)
int dx = 0;
int dy = 0;
@@ -156,6 +186,10 @@ void TiledPage::setTileLevels(int firstTileX, int firstTileY)
XLOG("setTileLevel tile: %x, fxy(%d, %d), level: %d", tile, firstTileX, firstTileY, d);
tile->setUsedLevel(d);
}
+
+ // clear the invalidated region as all tiles within that region have now
+ // been marked as dirty.
+ m_invalRegion.setEmpty();
}
void TiledPage::prepare(bool goingDown, bool goingLeft, int firstTileX, int firstTileY)
@@ -163,10 +197,13 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, int firstTileX, int firs
if (!m_glWebViewState)
return;
+ // update the tiles distance from the viewport
+ updateTileState(firstTileX, firstTileY);
+
int nbTilesWidth = m_glWebViewState->nbTilesWidth();
int nbTilesHeight = m_glWebViewState->nbTilesHeight();
- TileSet* highResSet = new TileSet(m_id, firstTileX, firstTileY, nbTilesHeight, nbTilesWidth);
+ TileSet* highResSet = new TileSet(this, nbTilesHeight, nbTilesWidth);
// We chose to display tiles depending on the scroll direction:
if (goingDown) {
@@ -178,23 +215,6 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, int firstTileX, int firs
prepareRow(goingLeft, nbTilesWidth, firstTileX, startingTileY - i, highResSet);
}
- // update the tiles distance from the viewport
- setTileLevels(firstTileX, firstTileY);
-
-
-#ifdef DEBUG
- XLOG("+++ BEFORE RESERVE TEXTURES (%d x %d) at (%d, %d), TiledPage %x",
- nbTilesWidth, nbTilesHeight, firstTileX, firstTileY, this);
- TilesManager::instance()->printTextures();
-#endif // DEBUG
- highResSet->reserveTextures();
-
-#ifdef DEBUG
- TilesManager::instance()->printTextures();
- XLOG("--- AFTER RESERVE TEXTURES (%d x %d) at (%d, %d), TiledPage %x",
- nbTilesWidth, nbTilesHeight, firstTileX, firstTileY, this);
-#endif // DEBUG
-
// schedulePaintForTileSet will take ownership of the highResSet here,
// so no delete necessary.
TilesManager::instance()->schedulePaintForTileSet(highResSet);
@@ -213,7 +233,7 @@ bool TiledPage::ready(int firstTileX, int firstTileY)
int x = j + firstTileX;
int y = i + firstTileY;
BaseTile* t = getBaseTile(x, y);
- if (!t || !t->isBitmapReady())
+ if (!t || !t->isTileReady())
return false;
}
}
@@ -260,10 +280,11 @@ void TiledPage::draw(float transparency, SkRect& viewport, int firstTileX, int f
#endif // DEBUG
}
-void TiledPage::paintBaseLayerContent(SkCanvas* canvas)
+int TiledPage::paintBaseLayerContent(SkCanvas* canvas)
{
if (m_glWebViewState)
- m_glWebViewState->paintBaseLayerContent(canvas);
+ return m_glWebViewState->paintBaseLayerContent(canvas);
+ return 0;
}
TiledPage* TiledPage::sibling()
diff --git a/WebCore/platform/graphics/android/TiledPage.h b/WebCore/platform/graphics/android/TiledPage.h
index 8be2361..62756ff 100644
--- a/WebCore/platform/graphics/android/TiledPage.h
+++ b/WebCore/platform/graphics/android/TiledPage.h
@@ -30,11 +30,13 @@
#include "BaseTile.h"
#include "SkCanvas.h"
+#include "SkRegion.h"
#include "TileSet.h"
namespace WebCore {
class GLWebViewState;
+class IntRect;
typedef std::pair<int, int> TileKey;
typedef HashMap<TileKey, BaseTile*> TileMap;
@@ -68,15 +70,17 @@ public:
void draw(float transparency, SkRect& viewport, int firstTileX, int firstTileY);
// used by individual tiles to generate the bitmap for their tile
- void paintBaseLayerContent(SkCanvas*);
+ int paintBaseLayerContent(SkCanvas*);
// used by individual tiles to get the information about the current picture
GLWebViewState* glWebViewState() { return m_glWebViewState; }
float scale() const { return m_scale; }
void setScale(float scale) { m_scale = scale; m_invScale = 1 / scale; }
+ void invalidateRect(const IntRect& invalRect, const int pictureCount);
+
private:
- void setTileLevels(int firstTileX, int firstTileY);
+ void updateTileState(int firstTileX, int firstTileY);
void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set);
BaseTile* getBaseTile(int x, int y);
@@ -86,6 +90,13 @@ private:
float m_scale;
float m_invScale;
GLWebViewState* m_glWebViewState;
+
+ // used to identify the tiles that have been invalidated (marked dirty) since
+ // the last time updateTileState() has been called. The region is stored in
+ // terms of the (x,y) coordinates used to determine the location of the tile
+ // within the page, not in content/view pixel coordinates.
+ SkRegion m_invalRegion;
+ int m_latestPictureInval;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp
index 54ca9ad..9ebfe02 100644
--- a/WebCore/platform/graphics/android/TilesManager.cpp
+++ b/WebCore/platform/graphics/android/TilesManager.cpp
@@ -136,8 +136,7 @@ void TilesManager::paintTexturesDefault()
#else
canvas->drawARGB(255, 255, 255, 255);
#endif // DEBUG
- PaintingInfo info;
- texture->producerUpdate(0, textureInfo, info);
+ texture->producerUpdate(textureInfo);
}
}
}
@@ -186,9 +185,9 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner)
}
}
if (farthestTexture && farthestTexture->acquire(owner)) {
- farthestTexture->setUsedLevel(0);
XLOG("farthest texture, getAvailableTexture(%x) => texture %x (level %d)",
owner, farthestTexture, farthestTexture->usedLevel());
+ farthestTexture->setUsedLevel(0);
return farthestTexture;
}