diff options
author | Derek Sollenberger <djsollen@google.com> | 2010-11-05 12:07:58 -0400 |
---|---|---|
committer | Derek Sollenberger <djsollen@google.com> | 2010-11-05 12:36:23 -0400 |
commit | a1e806ed3b2d9e2727d08cc2a3958fce501f6f33 (patch) | |
tree | 080f1f338514bb7ee83fd8b41007b0f2d7cc689c /WebCore | |
parent | 1e6843296fbdb863eaaaa99df71c7b333e7b7803 (diff) | |
download | external_webkit-a1e806ed3b2d9e2727d08cc2a3958fce501f6f33.zip external_webkit-a1e806ed3b2d9e2727d08cc2a3958fce501f6f33.tar.gz external_webkit-a1e806ed3b2d9e2727d08cc2a3958fce501f6f33.tar.bz2 |
Support partial invalidation of tiles based on webkit's inval rect.
This CL reverts the rollback of the original CL now that we have
fixed bug #3165953.
This reverts commit 144ccd9c8dba05ffaa0ae598f9b70032050fc20e.
Change-Id: Ibb5254f652ed95aa3b7b71bf24a2578c51e74a70
Diffstat (limited to 'WebCore')
-rw-r--r-- | WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp | 38 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h | 55 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/BaseTile.cpp | 103 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/BaseTile.h | 24 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/DoubleBufferedTexture.h | 5 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/GLWebViewState.cpp | 11 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/GLWebViewState.h | 27 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TexturesGenerator.cpp | 11 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TileSet.cpp | 32 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TileSet.h | 11 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TiledPage.cpp | 67 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TiledPage.h | 15 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TilesManager.cpp | 5 |
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..ff5d9ca 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 unsigned 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); + unsigned 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..8870cbf 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(const unsigned 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. + unsigned 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). + unsigned 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..4ad22d8 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) +unsigned 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..3eaabb3 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); + unsigned 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..358c1a8 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 unsigned 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) +unsigned 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..b532033 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*); + unsigned 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 unsigned 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; + unsigned 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; } |