summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp127
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.h12
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.cpp155
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.h29
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTileTexture.cpp9
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTileTexture.h10
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp18
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.h2
-rw-r--r--Source/WebCore/platform/graphics/android/PaintTileOperation.cpp36
-rw-r--r--Source/WebCore/platform/graphics/android/PaintTileOperation.h1
-rw-r--r--Source/WebCore/platform/graphics/android/TextureOwner.h1
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.cpp110
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.h18
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.cpp24
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.cpp125
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.h17
-rw-r--r--Source/WebCore/platform/graphics/android/TilesProfiler.cpp2
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp7
-rw-r--r--Source/WebKit/android/jni/PictureSet.cpp17
19 files changed, 382 insertions, 338 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index ca679fb..573ad6b 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -36,11 +36,14 @@
#include <wtf/CurrentTime.h>
#endif // USE(ACCELERATED_COMPOSITING)
-#ifdef DEBUG
-
#include <cutils/log.h>
#include <wtf/text/CString.h>
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
+
+#ifdef DEBUG
+
#undef XLOG
#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
@@ -57,8 +60,9 @@ using namespace android;
BaseLayerAndroid::BaseLayerAndroid()
#if USE(ACCELERATED_COMPOSITING)
- : m_glWebViewState(0),
- m_color(Color::white)
+ : m_glWebViewState(0)
+ , m_color(Color::white)
+ , m_scrollState(NotScrolling)
#endif
{
#ifdef DEBUG_COUNT
@@ -113,7 +117,7 @@ void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
#if USE(ACCELERATED_COMPOSITING)
bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
- double currentTime, bool* pagesSwapped)
+ double currentTime, bool* buffersSwappedPtr)
{
ZoomManager* zoomManager = m_glWebViewState->zoomManager();
@@ -126,94 +130,109 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
// Query the resulting state from the zoom manager
bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage();
- bool zooming = zoomManager->zooming();
// Display the current page
TiledPage* tiledPage = m_glWebViewState->frontPage();
TiledPage* nextTiledPage = m_glWebViewState->backPage();
tiledPage->setScale(zoomManager->currentScale());
- // Let's prepare the page if needed
+ // Let's prepare the page if needed so that it will start painting
if (prepareNextTiledPage) {
nextTiledPage->setScale(scale);
m_glWebViewState->setFutureViewport(viewportTileBounds);
m_glWebViewState->lockBaseLayerUpdate();
- nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, TiledPage::kVisibleBounds);
+ nextTiledPage->updateTileState(viewportTileBounds);
+ nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds,
+ TiledPage::VisibleBounds);
// Cancel pending paints for the foreground page
TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
}
// If we fired a request, let's check if it's ready to use
if (zoomManager->didFireRequest()) {
- if (nextTiledPage->ready(viewportTileBounds, zoomManager->futureScale()))
+ if (nextTiledPage->swapBuffersIfReady(viewportTileBounds,
+ zoomManager->futureScale(),
+ TiledPage::SwapWholePage))
zoomManager->setReceivedRequest(); // transition to received request state
}
float transparency = 1;
- bool doSwap = false;
+ bool doZoomPageSwap = false;
// If the page is ready, display it. We do a short transition between
// the two pages (current one and future one with the new scale factor)
if (zoomManager->didReceivedRequest()) {
float nextTiledPageTransparency = 1;
- zoomManager->processTransition(currentTime, scale, &doSwap,
+ zoomManager->processTransition(currentTime, scale, &doZoomPageSwap,
&nextTiledPageTransparency, &transparency);
nextTiledPage->draw(nextTiledPageTransparency, viewportTileBounds);
}
const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
- bool needsRedraw = false;
-
- static bool waitOnScrollFinish = false;
-
- if (m_glWebViewState->isScrolling()) {
- if (!waitOnScrollFinish) {
- waitOnScrollFinish = true;
-
- //started scrolling, lock updates
- m_glWebViewState->lockBaseLayerUpdate();
- }
- } else {
- // wait until all tiles are rendered before anything else
- if (waitOnScrollFinish) {
- //wait for the page to finish rendering, then go into swap mode
- if (tiledPage->ready(preZoomBounds, zoomManager->currentScale())) {
- m_glWebViewState->resetFrameworkInval();
- m_glWebViewState->unlockBaseLayerUpdate();
- waitOnScrollFinish = false;
- }
- //should be prepared, simply draw
- }
-
- if (!waitOnScrollFinish) {
- //completed page post-scroll
- if (!tiledPage->ready(preZoomBounds, zoomManager->currentScale())) {
- m_glWebViewState->lockBaseLayerUpdate();
+ // update scrolling state machine by querying glwebviewstate - note that the
+ // NotScrolling state is only set below
+ if (m_glWebViewState->isScrolling())
+ m_scrollState = Scrolling;
+ else if (m_scrollState == Scrolling)
+ m_scrollState = ScrollingFinishPaint;
+
+ bool scrolling = m_scrollState != NotScrolling;
+ bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
+
+ // When we aren't zooming, we should TRY and swap tile buffers if they're
+ // ready. When scrolling, we swap whatever's ready. Otherwise, buffer until
+ // the entire page is ready and then swap.
+ bool buffersSwapped = false;
+ if (!zooming) {
+ TiledPage::SwapMethod swapMethod;
+ if (scrolling)
+ swapMethod = TiledPage::SwapWhateverIsReady;
+ else
+ swapMethod = TiledPage::SwapWholePage;
+
+ buffersSwapped = tiledPage->swapBuffersIfReady(preZoomBounds,
+ zoomManager->currentScale(),
+ swapMethod);
+
+ if (buffersSwappedPtr && buffersSwapped)
+ *buffersSwappedPtr = true;
+ if (buffersSwapped) {
+ if (m_scrollState == ScrollingFinishPaint) {
+ m_scrollState = NotScrolling;
+ scrolling = false;
}
}
}
- if (!prepareNextTiledPage || tiledPage->ready(preZoomBounds, zoomManager->currentScale()))
- tiledPage->prepare(goingDown, goingLeft, preZoomBounds, TiledPage::kExpandedBounds);
- tiledPage->draw(transparency, preZoomBounds);
-
- if (zoomManager->scaleRequestState() != ZoomManager::kNoScaleRequest
- || !tiledPage->ready(preZoomBounds, zoomManager->currentScale()))
- needsRedraw = true;
-
- if (doSwap) {
+ if (doZoomPageSwap) {
zoomManager->setCurrentScale(scale);
m_glWebViewState->swapPages();
- if (pagesSwapped)
- *pagesSwapped = true;
+ if (buffersSwappedPtr)
+ *buffersSwappedPtr = true;
}
- // if no longer trailing behind invalidates, unlock (so invalidates can
- // go directly to the the TiledPages without deferral)
- if (!needsRedraw && !waitOnScrollFinish)
+ // If stuff is happening such that we need a redraw, lock updates to the
+ // base layer, and only then start painting.
+ bool needsRedraw = scrolling || zooming || !buffersSwapped;
+ if (needsRedraw)
+ m_glWebViewState->lockBaseLayerUpdate();
+ else
m_glWebViewState->unlockBaseLayerUpdate();
+ XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d",
+ scrolling, zooming, buffersSwapped, needsRedraw);
+
+ tiledPage->updateTileState(preZoomBounds);
+
+ // Only paint new textures if the base layer has been locked, but not if
+ // we're zooming since the new tiles won't be relevant soon anyway
+ if (needsRedraw && !zooming)
+ tiledPage->prepare(goingDown, goingLeft, preZoomBounds,
+ TiledPage::ExpandedBounds);
+
+ tiledPage->draw(transparency, preZoomBounds);
+
m_glWebViewState->paintExtras();
return needsRedraw;
}
@@ -221,13 +240,13 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
IntRect& viewRect, SkRect& visibleRect, float scale,
- bool* pagesSwapped)
+ bool* buffersSwappedPtr)
{
bool needsRedraw = false;
#if USE(ACCELERATED_COMPOSITING)
needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime,
- pagesSwapped);
+ buffersSwappedPtr);
if (!needsRedraw)
m_glWebViewState->resetFrameworkInval();
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
index 35ce24c..a42a372 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
@@ -38,6 +38,12 @@ namespace WebCore {
class BaseLayerAndroid : public Layer {
public:
+ enum ScrollState {
+ NotScrolling = 0,
+ Scrolling = 1,
+ ScrollingFinishPaint = 2
+ };
+
BaseLayerAndroid();
virtual ~BaseLayerAndroid();
@@ -56,12 +62,12 @@ public:
void drawCanvas(SkCanvas* canvas);
bool drawGL(double currentTime, LayerAndroid* compositedRoot, IntRect& rect,
- SkRect& viewport, float scale, bool* pagesSwapped);
+ SkRect& viewport, float scale, bool* buffersSwappedPtr);
void swapExtra(BaseLayerAndroid* base) { m_extra.swap(base->m_extra); }
private:
#if USE(ACCELERATED_COMPOSITING)
bool drawBasePictureInGL(SkRect& viewport, float scale, double currentTime,
- bool* pagesSwapped);
+ bool* buffersSwappedPtr);
GLWebViewState* m_glWebViewState;
android::Mutex m_drawLock;
@@ -70,6 +76,8 @@ private:
android::PictureSet m_content;
SkPicture m_extra;
SkRect m_previousVisible;
+
+ ScrollState m_scrollState;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp
index 2963ca7..0a87ffe 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp
@@ -59,15 +59,16 @@ BaseTile::BaseTile(bool isLayerTile)
, m_x(-1)
, m_y(-1)
, m_page(0)
- , m_usedLevel(-1)
- , m_texture(0)
+ , m_frontTexture(0)
+ , m_backTexture(0)
, m_scale(1)
, m_dirty(true)
, m_repaintPending(false)
- , m_usable(true)
, m_lastDirtyPicture(0)
, m_isTexturePainted(false)
, m_isLayerTile(isLayerTile)
+ , m_isSwapNeeded(false)
+ , m_drawCount(0)
{
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("BaseTile");
@@ -91,9 +92,10 @@ BaseTile::BaseTile(bool isLayerTile)
BaseTile::~BaseTile()
{
- setUsedLevel(-1);
- if (m_texture)
- m_texture->release(this);
+ if (m_backTexture)
+ m_backTexture->release(this);
+ if (m_frontTexture)
+ m_frontTexture->release(this);
delete m_renderer;
delete[] m_dirtyArea;
@@ -119,6 +121,7 @@ void BaseTile::setContents(TilePainter* painter, int x, int y, float scale)
m_x = x;
m_y = y;
m_scale = scale;
+ m_drawCount = TilesManager::instance()->getDrawGLCount();
}
void BaseTile::reserveTexture()
@@ -126,22 +129,30 @@ void BaseTile::reserveTexture()
BaseTileTexture* texture = TilesManager::instance()->getAvailableTexture(this);
android::AutoMutex lock(m_atomicSync);
- if (texture && m_texture != texture) {
- m_isTexturePainted = false;
- fullInval();
+ if (texture && m_backTexture != texture) {
+ m_isSwapNeeded = false; // no longer ready to swap
+ m_backTexture = texture;
+
+ // this is to catch when the front texture is stolen from beneath us. We
+ // should refine the stealing method to be simpler, and not require last
+ // moment checks like this
+ if (!m_frontTexture)
+ m_dirty = true;
}
- m_texture = texture;
- if (m_texture)
- m_texture->setUsedLevel(m_usedLevel);
}
bool BaseTile::removeTexture(BaseTileTexture* texture)
{
- XLOG("%x removeTexture res: %x... page %x", this, m_texture, m_page);
+ XLOG("%x removeTexture back %x front %x... page %x",
+ this, m_backTexture, m_frontTexture, m_page);
// We update atomically, so paintBitmap() can see the correct value
android::AutoMutex lock(m_atomicSync);
- if (m_texture == texture)
- m_texture = 0;
+ if (m_frontTexture == texture) {
+ m_frontTexture = 0;
+ m_dirty = true;
+ }
+ if (m_backTexture == texture)
+ m_backTexture = 0;
return true;
}
@@ -166,13 +177,6 @@ void BaseTile::markAsDirty(int unsigned pictureCount,
m_dirty = true;
}
-void BaseTile::setUsable(bool usable)
-{
- android::AutoMutex lock(m_atomicSync);
- m_usable = usable;
-}
-
-
bool BaseTile::isDirty()
{
android::AutoMutex lock(m_atomicSync);
@@ -191,81 +195,62 @@ void BaseTile::setRepaintPending(bool pending)
m_repaintPending = pending;
}
-void BaseTile::setUsedLevel(int usedLevel)
-{
- if (m_texture)
- m_texture->setUsedLevel(usedLevel);
- m_usedLevel = usedLevel;
-}
-
-int BaseTile::usedLevel()
-{
- if (m_texture)
- return m_texture->usedLevel();
- return m_usedLevel;
-}
-
-
void BaseTile::draw(float transparency, SkRect& rect, float scale)
{
if (m_x < 0 || m_y < 0 || m_scale != scale)
return;
- // No need to mutex protect reads of m_texture as it is only written to by
+ // No need to mutex protect reads of m_backTexture as it is only written to by
// the consumer thread.
- if (!m_texture) {
- XLOG("%x on page %x (%d, %d) trying to draw, but no m_texture!", this, m_page, x(), y());
+ if (!m_frontTexture)
return;
- }
// Early return if set to un-usable in purpose!
m_atomicSync.lock();
- bool usable = m_usable;
bool isTexturePainted = m_isTexturePainted;
m_atomicSync.unlock();
- if (!usable) {
- XLOG("early return at BaseTile::draw b/c tile set to unusable !");
- return;
- }
- if (!isTexturePainted) {
- XLOG("early return at BaseTile::draw b/c tile is not painted !");
+
+ if (!isTexturePainted)
return;
- }
- TextureInfo* textureInfo = m_texture->consumerLock();
+ TextureInfo* textureInfo = m_frontTexture->consumerLock();
if (!textureInfo) {
- XLOG("%x (%d, %d) trying to draw, but no textureInfo!", this, x(), y());
- m_texture->consumerRelease();
+ m_frontTexture->consumerRelease();
return;
}
- if (m_texture->readyFor(this)) {
- XLOG("draw tile %x : %d, %d, %.2f with texture %x", this, x(), y(), m_scale, m_texture);
+ if (m_frontTexture->readyFor(this)) {
if (isLayerTile())
TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(),
- rect, m_texture->m_ownTextureId,
+ rect, m_frontTexture->m_ownTextureId,
transparency, true);
else
- TilesManager::instance()->shader()->drawQuad(rect, m_texture->m_ownTextureId,
+ TilesManager::instance()->shader()->drawQuad(rect, m_frontTexture->m_ownTextureId,
transparency);
- }
- m_texture->consumerRelease();
+ } else
+ m_dirty = true;
+
+ m_frontTexture->consumerRelease();
}
bool BaseTile::isTileReady()
{
- if (!m_texture)
+ // Return true if the tile's most recently drawn texture is up to date
+ android::AutoMutex lock(m_atomicSync);
+ BaseTileTexture * texture = m_isSwapNeeded ? m_backTexture : m_frontTexture;
+
+ if (!texture)
return false;
- if (m_texture->owner() != this)
+
+ if (texture->owner() != this)
return false;
- android::AutoMutex lock(m_atomicSync);
if (m_dirty)
return false;
- m_texture->consumerLock();
- bool ready = m_texture->readyFor(this);
- m_texture->consumerRelease();
+ texture->consumerLock();
+ bool ready = texture->readyFor(this);
+ texture->consumerRelease();
if (ready)
return true;
@@ -302,7 +287,7 @@ void BaseTile::paintBitmap()
// can be updated by other threads without consequence.
m_atomicSync.lock();
bool dirty = m_dirty;
- BaseTileTexture* texture = m_texture;
+ BaseTileTexture* texture = m_backTexture;
SkRegion dirtyArea = m_dirtyArea[m_currentDirtyAreaIndex];
float scale = m_scale;
const int x = m_x;
@@ -320,7 +305,7 @@ void BaseTile::paintBitmap()
// 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) {
+ if (texture->owner() != this) {
texture->producerRelease();
return;
}
@@ -412,16 +397,13 @@ void BaseTile::paintBitmap()
pictureCount = m_renderer->renderTiledContent(renderInfo);
}
- XLOG("%x update texture %x for tile %d, %d scale %.2f (m_scale: %.2f)", this, textureInfo, x, y, scale, m_scale);
-
m_atomicSync.lock();
#if DEPRECATED_SURFACE_TEXTURE_MODE
texture->setTile(textureInfo, x, y, scale, painter, pictureCount);
#endif
texture->producerReleaseAndSwap();
-
- if (texture == m_texture) {
+ if (texture == m_backTexture) {
m_isTexturePainted = true;
// set the fullrepaint flags
@@ -451,12 +433,43 @@ void BaseTile::paintBitmap()
m_dirty = true;
if (!m_dirty)
- m_usable = true;
+ m_isSwapNeeded = true;
}
m_atomicSync.unlock();
}
+void BaseTile::discardTextures() {
+ android::AutoMutex lock(m_atomicSync);
+ if (m_frontTexture) {
+ m_frontTexture->release(this);
+ m_frontTexture = 0;
+ }
+ if (m_backTexture) {
+ m_backTexture->release(this);
+ m_backTexture = 0;
+ }
+ m_dirty = true;
+}
+
+bool BaseTile::swapTexturesIfNeeded() {
+ android::AutoMutex lock(m_atomicSync);
+ if (m_isSwapNeeded) {
+ // discard old texture and swap the new one in its place
+ if (m_frontTexture)
+ m_frontTexture->release(this);
+
+ XLOG("%p's frontTexture was %p, now becoming %p", this, m_frontTexture, m_backTexture);
+ m_frontTexture = m_backTexture;
+ m_backTexture = 0;
+ m_isSwapNeeded = false;
+ XLOG("display texture for %d, %d front is now %p, texture is %p",
+ m_x, m_y, m_frontTexture, m_backTexture);
+ return true;
+ }
+ return false;
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h
index 0770b30..4c9650f 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.h
+++ b/Source/WebCore/platform/graphics/android/BaseTile.h
@@ -68,12 +68,11 @@ public:
void setContents(TilePainter* painter, int x, int y, float scale);
void setPage(TiledPage* page) { m_page = page; }
- bool isAvailable() const { return !m_texture; }
void reserveTexture();
- void setUsedLevel(int);
- int usedLevel();
+
bool isTileReady();
+
void draw(float transparency, SkRect& rect, float scale);
// the only thread-safe function called by the background thread
@@ -88,13 +87,16 @@ public:
bool isDirty();
bool isRepaintPending();
void setRepaintPending(bool pending);
- void setUsable(bool usable);
float scale() const { return m_scale; }
void fullInval();
int x() const { return m_x; }
int y() const { return m_y; }
- BaseTileTexture* texture() { return m_texture; }
+ BaseTileTexture* frontTexture() { return m_frontTexture; }
+ BaseTileTexture* backTexture() { return m_backTexture; }
+ void discardTextures();
+ bool swapTexturesIfNeeded();
+ unsigned long long drawCount() { return m_drawCount; }
void setGLWebViewState(GLWebViewState* state) { m_glWebViewState = state; }
@@ -114,15 +116,16 @@ private:
TiledPage* m_page;
// The remaining variables can be updated throughout the lifetime of the object
- int m_usedLevel;
- BaseTileTexture* m_texture;
+
+ BaseTileTexture* m_frontTexture;
+ BaseTileTexture* m_backTexture;
float m_scale;
- // used to signal that the that the tile is out-of-date and needs to be redrawn
+
+ // used to signal that the that the tile is out-of-date and needs to be
+ // redrawn in the backTexture
bool m_dirty;
// used to signal that a repaint is pending
bool m_repaintPending;
- // used to signal whether or not the draw can use this tile.
- bool m_usable;
// 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.
@@ -145,6 +148,12 @@ private:
BaseRenderer* m_renderer;
bool m_isLayerTile;
+ bool m_isSwapNeeded;
+
+ // the most recent GL draw before this tile was prepared. used for
+ // prioritization and caching. tiles with old drawcounts and textures they
+ // own are used for new tiles and rendering
+ unsigned long long m_drawCount;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
index 7c6fb7a..9db819c 100644
--- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
@@ -52,7 +52,6 @@ namespace WebCore {
BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h)
: DoubleBufferedTexture(eglGetCurrentContext(),
TilesManager::instance()->getSharedTextureMode())
- , m_usedLevel(-1)
, m_owner(0)
, m_delayedReleaseOwner(0)
, m_delayedRelease(false)
@@ -269,10 +268,10 @@ bool BaseTileTexture::readyFor(BaseTile* baseTile)
(info->m_inverted == TilesManager::instance()->invertedScreen()))
return true;
- XLOG("readyFor return false for tile x, y (%d %d) texId %d ,"
- " BaseTileTexture %p, BaseTile is %p",
- baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile);
-
+ XLOG("texture %p readyFor return false for tile x, y (%d %d) texId %d ,"
+ " BaseTileTexture %p, BaseTile is %p, SCALE %f, painter %p, inv %d",
+ this, baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile,
+ baseTile->scale(), baseTile->painter(), TilesManager::instance()->invertedScreen());
return false;
}
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h
index bc66195..9c94a53 100644
--- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h
@@ -105,15 +105,6 @@ public:
// swaps) the texture.
virtual void producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap);
- // The level can be one of the following values:
- // * -1 for an unused texture.
- // * 0 for the tiles intersecting with the viewport.
- // * n where n > 0 for the distance between the viewport and the tile.
- // We use this to prioritize the order in which we reclaim textures, see
- // TilesManager::getAvailableTexture() for more information.
- int usedLevel() { return m_usedLevel; }
- void setUsedLevel(int used) { m_usedLevel = used; }
-
// allows consumer thread to assign ownership of the texture to the tile. It
// returns false if ownership cannot be transferred because the tile is busy
bool acquire(TextureOwner* owner, bool force = false);
@@ -149,7 +140,6 @@ private:
TextureTileInfo m_ownTextureTileInfo;
SkSize m_size;
- int m_usedLevel;
SkBitmap::Config m_config;
TextureOwner* m_owner;
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index bc07925..f030e52 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -131,8 +131,8 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval
{
android::Mutex::Autolock lock(m_baseLayerLock);
if (!layer || isPictureAfterFirstLayout) {
- m_tiledPageA->setUsable(false);
- m_tiledPageB->setUsable(false);
+ m_tiledPageA->discardTextures();
+ m_tiledPageB->discardTextures();
}
if (isPictureAfterFirstLayout) {
m_baseLayerUpdate = true;
@@ -355,9 +355,9 @@ void GLWebViewState::swapPages()
{
android::Mutex::Autolock lock(m_tiledPageLock);
m_usePageA ^= true;
- TiledPage* working = m_usePageA ? m_tiledPageB : m_tiledPageA;
- if (zoomManager()->swapPages())
- TilesManager::instance()->resetTextureUsage(working);
+ TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA;
+ zoomManager()->swapPages();
+ oldPage->discardTextures();
}
int GLWebViewState::baseContentWidth()
@@ -489,15 +489,16 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
- IntRect& clip, float scale, bool* pagesSwapped)
+ IntRect& clip, float scale, bool* buffersSwappedPtr)
{
glFinish();
- TilesManager::instance()->registerGLWebViewState(this);
+
TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
viewport.fTop,
viewport.fRight,
viewport.fBottom,
scale);
+ TilesManager::instance()->incDrawGLCount();
#ifdef DEBUG
TilesManager::instance()->getTilesTracker()->clear();
@@ -552,7 +553,8 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
// set up zoom manager, shaders, etc.
m_backgroundColor = baseLayer->getBackgroundColor();
double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
- bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect, viewport, scale, pagesSwapped);
+ bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect,
+ viewport, scale, buffersSwappedPtr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h
index 9bda481..a7803de 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h
@@ -212,7 +212,7 @@ public:
bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
IntRect& webViewRect, int titleBarHeight,
- IntRect& clip, float scale, bool* pagesSwapped);
+ IntRect& clip, float scale, bool* buffersSwappedPtr);
#ifdef MEASURES_PERF
void dumpMeasures();
diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
index 3aac918..4366ad6 100644
--- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
@@ -73,26 +73,32 @@ void PaintTileOperation::run()
int PaintTileOperation::priority()
{
- if (!m_tile || m_tile->usedLevel() < 0)
+ if (!m_tile)
return -1;
- // for now, use a constant value for layers,
- // lower than the base layer tiles (as layers
- // will always be on top of the base surface)
+ int priority;
if (m_tile->isLayerTile())
- return -2;
+ priority = -2;
+ else {
+ bool goingDown = m_tile->page()->scrollingDown();
+ SkIRect *rect = m_tile->page()->expandedTileBounds();
+ int firstTileX = rect->fLeft;
+ int nbTilesWidth = rect->width();
+ priority = m_tile->x() - firstTileX;
+ if (goingDown)
+ priority += (rect->fBottom - m_tile->y()) * nbTilesWidth;
+ else
+ priority += (m_tile->y() - rect->fTop) * nbTilesWidth;
+ }
+ if (m_tile->frontTexture()) {
+ // de-prioritize old tiles that have something visible
+ unsigned long long currentDraw = TilesManager::instance()->getDrawGLCount();
+ unsigned long long drawDelta = currentDraw - m_tile->drawCount();
+ int cappedDrawDelta = (int)std::max(drawDelta, (unsigned long long)1000);
+ priority += cappedDrawDelta * 100000;
+ }
- bool goingDown = m_tile->page()->scrollingDown();
- SkIRect *rect = m_tile->page()->expandedTileBounds();
- int firstTileX = rect->fLeft;
- int nbTilesWidth = rect->width();
- int priority = m_tile->x() - firstTileX;
- if (goingDown)
- priority += (rect->fBottom - m_tile->y()) * nbTilesWidth;
- else
- priority += (m_tile->y() - rect->fTop) * nbTilesWidth;
- priority += m_tile->usedLevel() * 100000;
return priority;
}
diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h
index 72a4125..57bbd8b 100644
--- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h
@@ -39,6 +39,7 @@ public:
virtual ~PaintTileOperation();
virtual bool operator==(const QueuedOperation* operation);
virtual void run();
+ // returns a rendering priority for m_tile, lower values are processed faster
virtual int priority();
TilePainter* painter() { return m_tile->painter(); }
float scale() { return m_tile->scale(); }
diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h
index d0c60fb..5434dbf 100644
--- a/Source/WebCore/platform/graphics/android/TextureOwner.h
+++ b/Source/WebCore/platform/graphics/android/TextureOwner.h
@@ -43,6 +43,7 @@ public:
virtual GLWebViewState* state() = 0;
virtual bool samePageAs(Layer* root) { return false; }
virtual bool isRepaintPending() = 0;
+ virtual unsigned long long drawCount() = 0;
};
}
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp
index 95603af..b6a0c47 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp
@@ -100,19 +100,20 @@ TiledPage::~TiledPage()
BaseTile* TiledPage::getBaseTile(int x, int y) const
{
+ // TODO: replace loop over array with HashMap indexing
for (int j = 0; j < m_baseTileSize; j++) {
BaseTile& tile = m_baseTiles[j];
- if (tile.x() == x && tile.y() == y && !tile.isAvailable())
+ if (tile.x() == x && tile.y() == y)
return &tile;
}
return 0;
}
-void TiledPage::setUsable(bool usable)
+void TiledPage::discardTextures()
{
for (int j = 0; j < m_baseTileSize; j++) {
BaseTile& tile = m_baseTiles[j];
- tile.setUsable(usable);
+ tile.discardTextures();
}
return;
}
@@ -163,57 +164,44 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y
currentTile = &tile;
break;
}
- if (!availableTile && tile.isAvailable())
+
+ if (!availableTile || (tile.drawCount() < availableTile->drawCount()))
availableTile = &tile;
}
if (!currentTile && availableTile) {
+ XLOG("STEALING tile %d, %d (draw count %llu) for tile %d, %d",
+ availableTile->x(), availableTile->y(), availableTile->drawCount(), x, y);
currentTile = availableTile;
}
+ if (!currentTile) {
+ XLOG("ERROR: No tile available for tile %d %d", x, y);
+ }
+
if (currentTile) {
currentTile->setGLWebViewState(m_glWebViewState);
- currentTile->setContents(this, x, y, m_scale);
currentTile->setPage(this);
+ currentTile->setContents(this, x, y, m_scale);
+
+ // TODO: move below (which is largely the same for layers / tiled
+ // page) into prepare() function
+
// ensure there is a texture associated with the tile and then check to
// see if the texture is dirty and in need of repainting
- currentTile->reserveTexture();
- updateTileUsedLevel(tileBounds, *currentTile);
- if (currentTile->isDirty() && !currentTile->isRepaintPending()) {
+ if (currentTile->isDirty() || !currentTile->frontTexture())
+ currentTile->reserveTexture();
+ if (currentTile->backTexture()
+ && currentTile->isDirty()
+ && !currentTile->isRepaintPending()) {
PaintTileOperation *operation = new PaintTileOperation(currentTile);
TilesManager::instance()->scheduleOperation(operation);
- } else if (currentTile->isDirty()) {
- XLOG("Tile %dx%d is dirty, but awaiting repaint", currentTile->x(), currentTile->y());
}
}
}
}
-void TiledPage::updateTileUsedLevel(const SkIRect& tileBounds, BaseTile& tile)
-{
- const int lastTileX = tileBounds.fRight - 1;
- const int lastTileY = tileBounds.fBottom - 1;
-
- // set the used level of the tile (e.g. distance from the viewport)
- int dx = 0;
- int dy = 0;
-
- if (tileBounds.fLeft > tile.x())
- dx = tileBounds.fLeft - tile.x();
- else if (lastTileX < tile.x())
- dx = tile.x() - lastTileX;
-
- if (tileBounds.fTop > tile.y())
- dy = tileBounds.fTop - tile.y();
- else if (lastTileY < tile.y())
- dy = tile.y() - lastTileY;
-
- int d = std::max(dx, dy);
-
- tile.setUsedLevel(d);
-}
-
void TiledPage::updateTileState(const SkIRect& tileBounds)
{
if (!m_glWebViewState || tileBounds.isEmpty()) {
@@ -226,15 +214,9 @@ void TiledPage::updateTileState(const SkIRect& tileBounds)
BaseTile& tile = m_baseTiles[x];
- // if the tile no longer has a texture then proceed to the next tile
- if (tile.isAvailable())
- 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, m_invalTilesRegion);
-
- updateTileUsedLevel(tileBounds, tile);
}
// clear the invalidated region as all tiles within that region have now
@@ -266,7 +248,7 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
int nTilesToPrepare = nbTilesWidth * nbTilesHeight;
int nMaxTilesPerPage = m_baseTileSize / 2;
- if (bounds == kExpandedBounds) {
+ if (bounds == ExpandedBounds) {
// prepare tiles outside of the visible bounds
int expandX = m_glWebViewState->expandedTileBoundsX();
int expandY = m_glWebViewState->expandedTileBoundsY();
@@ -296,7 +278,7 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
m_prepare = true;
}
-bool TiledPage::ready(const SkIRect& tileBounds, float scale)
+bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale, SwapMethod swap)
{
if (!m_glWebViewState)
return false;
@@ -307,17 +289,43 @@ bool TiledPage::ready(const SkIRect& tileBounds, float scale)
if (m_scale != scale)
return false;
- for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
- for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
- BaseTile* t = getBaseTile(x, y);
- if (!t || !t->isTileReady())
- return false;
+ int swaps = 0;
+ if (swap == SwapWholePage) {
+ for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
+ for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
+ BaseTile* t = getBaseTile(x, y);
+ if (!t || !t->isTileReady())
+ return false;
+ }
+ }
+ for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
+ for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
+ BaseTile* t = getBaseTile(x, y);
+ if (t->swapTexturesIfNeeded())
+ swaps++;
+ }
}
+ XLOG("%p whole page swapped %d textures, returning true", this, swaps);
+ return true;
+ } else { // SwapWhateveryIsReady
+ bool fullSwap = true;
+ for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
+ for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
+ BaseTile* t = getBaseTile(x, y);
+ if (!t || !t->isTileReady())
+ fullSwap = false;
+ else {
+ if (t->swapTexturesIfNeeded())
+ swaps++;
+ }
+ }
+ }
+ XLOG("%p greedy swap swapped %d tiles, returning %d", this, swaps, fullSwap);
+ return fullSwap;
}
- m_prepare = false;
- return true;
}
+
void TiledPage::draw(float transparency, const SkIRect& tileBounds)
{
if (!m_glWebViewState)
@@ -332,11 +340,13 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds)
actualTileBounds.fLeft -= m_glWebViewState->expandedTileBoundsX();
actualTileBounds.fRight += m_glWebViewState->expandedTileBoundsX();
+ actualTileBounds.fTop = std::max(0, actualTileBounds.fTop);
+ actualTileBounds.fLeft = std::max(0, actualTileBounds.fLeft);
+
for (int j = 0; j < m_baseTileSize; j++) {
BaseTile& tile = m_baseTiles[j];
bool tileInView = actualTileBounds.contains(tile.x(), tile.y());
if (tileInView) {
-
SkRect rect;
rect.fLeft = tile.x() * tileWidth;
rect.fTop = tile.y() * tileHeight;
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h
index 56a34f4..14306eb 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.h
+++ b/Source/WebCore/platform/graphics/android/TiledPage.h
@@ -52,8 +52,12 @@ class IntRect;
class TiledPage : public TilePainter {
public:
enum PrepareBounds {
- kExpandedBounds = 0,
- kVisibleBounds = 1
+ ExpandedBounds = 0,
+ VisibleBounds = 1
+ };
+ enum SwapMethod {
+ SwapWhateverIsReady = 0,
+ SwapWholePage = 1
};
TiledPage(int id, GLWebViewState* state);
@@ -64,8 +68,12 @@ public:
// prepare the page for display on the screen
void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds);
+ void updateTileState(const SkIRect& tileBounds);
+
// check to see if the page is ready for display
- bool ready(const SkIRect& tileBounds, float scale);
+
+ // swap 'buffers' by swapping each modified texture
+ bool swapBuffersIfReady(const SkIRect& tileBounds, float scale, SwapMethod swap);
// draw the page on the screen
void draw(float transparency, const SkIRect& tileBounds);
@@ -83,15 +91,13 @@ public:
void setScale(float scale) { m_scale = scale; m_invScale = 1 / scale; }
void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount);
- void setUsable(bool usable);
+ void discardTextures();
void updateBaseTileSize();
bool scrollingDown() { return m_scrollingDown; }
SkIRect* expandedTileBounds() { return &m_expandedTileBounds; }
private:
- void updateTileState(const SkIRect& tileBounds);
void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds);
- void updateTileUsedLevel(const SkIRect& tileBounds, BaseTile& tile);
BaseTile* getBaseTile(int x, int y) const;
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
index 1aac44d..c1fb4d1 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
@@ -68,7 +68,6 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint)
for (unsigned int i = 0; i < m_tiles.size(); i++) {
BaseTile* tile = m_tiles[i];
- tile->setUsedLevel(-1);
if (!m_dirtyRegion.isEmpty())
tile->markAsDirty(1, m_dirtyRegion);
}
@@ -130,19 +129,16 @@ void TiledTexture::prepareTile(bool repaint, int x, int y)
tile = new BaseTile(true);
m_tiles.append(tile);
}
- tile->reserveTexture();
- if (!tile->texture())
- return;
tile->setContents(this, x, y, m_surface->scale());
- tile->setUsedLevel(0);
- bool schedule = false;
- if (tile->isDirty())
- schedule = true;
+ // TODO: move below (which is largely the same for layers / tiled page) into
+ // prepare() function
+ if (tile->isDirty() || !tile->frontTexture())
+ tile->reserveTexture();
LayerAndroid* layer = m_surface->layer();
- if (schedule && layer && !tile->isRepaintPending()) {
+ if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending() && layer) {
PaintTileOperation *operation = new PaintTileOperation(tile, m_surface);
TilesManager::instance()->scheduleOperation(operation);
}
@@ -187,11 +183,13 @@ bool TiledTexture::draw()
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());
+ 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();
tile->draw(m_surface->opacity(), rect, m_surface->scale());
#ifdef DEBUG
- TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->texture());
+ TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
#endif
}
}
@@ -241,7 +239,9 @@ bool TiledTexture::owns(BaseTileTexture* texture)
{
for (unsigned int i = 0; i < m_tiles.size(); i++) {
BaseTile* tile = m_tiles[i];
- if (tile->texture() == texture)
+ if (tile->frontTexture() == texture)
+ return true;
+ if (tile->backTexture() == texture)
return true;
}
return false;
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp
index 57c38cf..2c263e3 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp
@@ -100,7 +100,7 @@ TilesManager::TilesManager()
, m_showVisualIndicator(false)
, m_invertedScreen(false)
, m_invertedScreenSwitch(false)
- , m_drawRegistrationCount(0)
+ , m_drawGLCount(0)
{
XLOG("TilesManager ctor");
m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
@@ -164,27 +164,14 @@ void TilesManager::printTextures()
x = o->x();
y = o->y();
}
- XLOG("[%d] texture %x usedLevel: %d busy: %d owner: %x (%d, %d) page: %x scale: %.2f",
- i, texture, texture->usedLevel(),
+ XLOG("[%d] texture %x busy: %d owner: %x (%d, %d) page: %x scale: %.2f",
+ i, texture,
texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0);
}
XLOG("------");
#endif // DEBUG
}
-void TilesManager::resetTextureUsage(TiledPage* page)
-{
- android::Mutex::Autolock lock(m_texturesLock);
- for (unsigned int i = 0; i < m_textures.size(); i++) {
- BaseTileTexture* texture = m_textures[i];
- TextureOwner* owner = texture->owner();
- if (owner) {
- if (owner->page() == page)
- texture->setUsedLevel(-1);
- }
- }
-}
-
void TilesManager::swapLayersTextures(LayerAndroid* oldTree, LayerAndroid* newTree)
{
if (oldTree)
@@ -227,81 +214,69 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner)
android::Mutex::Autolock lock(m_texturesLock);
// Sanity check that the tile does not already own a texture
- if (owner->texture() && owner->texture()->owner() == owner) {
- owner->texture()->setUsedLevel(0);
- XLOG("same owner (%d, %d), getAvailableTexture(%x) => texture %x",
- owner->x(), owner->y(), owner, owner->texture());
+ if (owner->backTexture() && owner->backTexture()->owner() == owner) {
+ XLOG("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x",
+ owner->x(), owner->y(), owner, owner->backTexture());
if (owner->isLayerTile())
- m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->texture()));
+ m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture()));
else
- m_availableTextures.remove(m_availableTextures.find(owner->texture()));
- return owner->texture();
+ m_availableTextures.remove(m_availableTextures.find(owner->backTexture()));
+ return owner->backTexture();
}
+ WTF::Vector<BaseTileTexture*>* availableTexturePool;
if (owner->isLayerTile()) {
- BaseTileTexture* layerTexture = 0;
- unsigned int max = m_availableTilesTextures.size();
- for (unsigned int i = 0; i < max; i++) {
- BaseTileTexture* texture = m_availableTilesTextures[i];
- if (texture->owner() && texture->owner()->isRepaintPending())
- continue;
- if (!texture->owner() && texture->acquire(owner)) {
- layerTexture = texture;
- break;
- }
- if (texture->usedLevel() != 0 && texture->acquire(owner)) {
- layerTexture = texture;
- break;
- }
- if (texture->scale() != owner->scale() && texture->acquire(owner)) {
- layerTexture = texture;
- break;
- }
- }
- if (layerTexture)
- m_availableTilesTextures.remove(m_availableTilesTextures.find(layerTexture));
- return layerTexture;
+ availableTexturePool = &m_availableTilesTextures;
+ } else {
+ availableTexturePool = &m_availableTextures;
}
// The heuristic for selecting a texture is as follows:
- // 1. If usedLevel == -1, break with that one
- // 2. Otherwise, select the highest usedLevel available
- // 3. Break ties with the lowest LRU(RecentLevel) valued GLWebViewState
+ // 1. If a tile isn't owned, break with that one
+ // 2. If we find a tile in the same page with a different scale,
+ // it's old and not visible. Break with that one
+ // 3. Otherwise, use the least recently prepared tile
BaseTileTexture* farthestTexture = 0;
- int farthestTextureLevel = 0;
- unsigned int lowestDrawCount = ~0; //maximum uint
- const unsigned int max = m_availableTextures.size();
+ unsigned long long oldestDrawCount = ~0; //maximum u64
+ const unsigned int max = availableTexturePool->size();
for (unsigned int i = 0; i < max; i++) {
- BaseTileTexture* texture = m_availableTextures[i];
-
- if (texture->usedLevel() == -1) { // found an unused texture, grab it
+ BaseTileTexture* texture = (*availableTexturePool)[i];
+ TextureOwner* currentOwner = texture->owner();
+ if (!currentOwner) {
farthestTexture = texture;
break;
}
- int textureLevel = texture->usedLevel();
- unsigned int textureDrawCount = getGLWebViewStateDrawCount(texture->owner()->state());
+ if (currentOwner->page() == owner->page() && texture->scale() != owner->scale()) {
+ // if we render the back page with one scale, then another while
+ // still zooming, we recycle the tiles with the old scale instead of
+ // taking ones from the front page
+ farthestTexture = texture;
+ break;
+ }
- // if (higher distance or equal distance but less recently rendered)
- if (farthestTextureLevel < textureLevel
- || ((farthestTextureLevel == textureLevel) && (lowestDrawCount > textureDrawCount))) {
+ unsigned long long textureDrawCount = currentOwner->drawCount();
+ if (oldestDrawCount > textureDrawCount) {
farthestTexture = texture;
- farthestTextureLevel = textureLevel;
- lowestDrawCount = textureDrawCount;
+ oldestDrawCount = textureDrawCount;
}
}
+ TextureOwner* previousOwner = farthestTexture->owner();
if (farthestTexture && farthestTexture->acquire(owner)) {
- XLOG("farthest texture, getAvailableTexture(%x) => texture %x (level %d, drawCount %d)",
- owner, farthestTexture, farthestTextureLevel, lowestDrawCount);
- farthestTexture->setUsedLevel(0);
- m_availableTextures.remove(m_availableTextures.find(farthestTexture));
+ if (previousOwner) {
+ XLOG("%s texture %p stolen from tile %d, %d, drawCount was %llu",
+ owner->isLayerTile() ? "LAYER" : "BASE",
+ farthestTexture, owner->x(), owner->y(), oldestDrawCount);
+ }
+
+ availableTexturePool->remove(availableTexturePool->find(farthestTexture));
return farthestTexture;
}
- XLOG("Couldn't find an available texture for BaseTile %x (%d, %d) !!!",
- owner, owner->x(), owner->y());
+ XLOG("Couldn't find an available texture for tile %x (%d, %d) out of %d available!!!",
+ owner, owner->x(), owner->y(), max);
#ifdef DEBUG
printTextures();
#endif // DEBUG
@@ -362,27 +337,11 @@ float TilesManager::layerTileHeight()
return LAYER_TILE_HEIGHT;
}
-void TilesManager::registerGLWebViewState(GLWebViewState* state)
-{
- m_glWebViewStateMap.set(state, m_drawRegistrationCount);
- m_drawRegistrationCount++;
- XLOG("now state %p, total of %d states", state, m_glWebViewStateMap.size());
-}
-
void TilesManager::unregisterGLWebViewState(GLWebViewState* state)
{
// Discard the whole queue b/c we lost GL context already.
// Note the real updateTexImage will still wait for the next draw.
transferQueue()->discardQueue();
-
- m_glWebViewStateMap.remove(state);
- XLOG("state %p now removed, total of %d states", state, m_glWebViewStateMap.size());
-}
-
-unsigned int TilesManager::getGLWebViewStateDrawCount(GLWebViewState* state)
-{
- XLOG("looking up state %p, contains=%s", state, m_glWebViewStateMap.contains(state) ? "TRUE" : "FALSE");
- return m_glWebViewStateMap.find(state)->second;
}
TilesManager* TilesManager::instance()
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h
index a383a2e..513494c 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/TilesManager.h
@@ -108,7 +108,6 @@ public:
static float tileHeight();
static float layerTileWidth();
static float layerTileHeight();
- void registerGLWebViewState(GLWebViewState* state);
void unregisterGLWebViewState(GLWebViewState* state);
void allocateTiles();
@@ -165,6 +164,16 @@ public:
m_shader.setContrast(contrast);
}
+ void incDrawGLCount()
+ {
+ m_drawGLCount++;
+ }
+
+ unsigned long long getDrawGLCount()
+ {
+ return m_drawGLCount;
+ }
+
private:
TilesManager();
@@ -206,13 +215,9 @@ private:
VideoLayerManager m_videoLayerManager;
- HashMap<GLWebViewState*, unsigned int> m_glWebViewStateMap;
- unsigned int m_drawRegistrationCount;
-
- unsigned int getGLWebViewStateDrawCount(GLWebViewState* state);
-
TilesProfiler m_profiler;
TilesTracker m_tilesTracker;
+ unsigned long long m_drawGLCount;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp
index 653d525..0271ee3 100644
--- a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp
+++ b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp
@@ -122,7 +122,7 @@ void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView)
}
m_records.last().append(TileProfileRecord(
left, top, right, bottom,
- scale, isReady, tile.usedLevel()));
+ scale, isReady, (int)tile.drawCount()));
XLOG("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale);
}
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
index 851d02c..b73f388 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -113,7 +113,7 @@ bool TransferQueue::checkObsolete(int index)
return true;
}
- BaseTileTexture* baseTileTexture = baseTilePtr->texture();
+ BaseTileTexture* baseTileTexture = baseTilePtr->backTexture();
if (!baseTileTexture) {
XLOG("Invalid baseTileTexture , such that the tile is obsolete");
return true;
@@ -248,7 +248,7 @@ void TransferQueue::updateDirtyBaseTiles()
// the queue. Then either move on to next item or copy the content.
BaseTileTexture* destTexture = 0;
if (!obsoleteBaseTile)
- destTexture = m_transferQueue[index].savedBaseTilePtr->texture();
+ destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture();
m_sharedSurfaceTexture->updateTexImage();
@@ -271,9 +271,10 @@ void TransferQueue::updateDirtyBaseTiles()
// texturesTileInfo.
destTexture->setOwnTextureTileInfoFromQueue(&m_transferQueue[index].tileInfo);
- XLOG("Blit tile x, y %d %d to destTexture->m_ownTextureId %d",
+ XLOG("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d",
m_transferQueue[index].tileInfo.m_x,
m_transferQueue[index].tileInfo.m_y,
+ destTexture,
destTexture->m_ownTextureId);
}
index = (index + 1) % ST_BUFFER_NUMBER;
diff --git a/Source/WebKit/android/jni/PictureSet.cpp b/Source/WebKit/android/jni/PictureSet.cpp
index 3c62205..839a887 100644
--- a/Source/WebKit/android/jni/PictureSet.cpp
+++ b/Source/WebKit/android/jni/PictureSet.cpp
@@ -155,6 +155,11 @@ void PictureSet::add(const SkRegion& area, SkPicture* picture,
Bucket* PictureSet::getBucket(int x, int y)
{
+ // only create buckets for valid, positive coordinates, ignore and return
+ // NULL otherwise
+ if (x < 0 || y < 0)
+ return 0;
+
BucketPosition position(x+1, y+1);
if (!mBuckets.contains(position)) {
Bucket* bucket = new Bucket();
@@ -277,6 +282,10 @@ void PictureSet::gatherBucketsForArea(WTF::Vector<Bucket*>& list, const SkIRect&
{
int maxSize = BUCKET_SIZE;
+ XLOG("\n--- gatherBucketsForArea for rect %d, %d, %d, %d (%d x %d)",
+ rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
+ rect.width(), rect.height());
+
int x = rect.fLeft;
int y = rect.fTop;
int firstTileX = rect.fLeft / maxSize;
@@ -288,7 +297,8 @@ void PictureSet::gatherBucketsForArea(WTF::Vector<Bucket*>& list, const SkIRect&
for (int j = firstTileY; j <= lastTileY; j++) {
Bucket* bucket = getBucket(i, j);
XLOG("gather bucket %x for %d, %d", bucket, i+1, j+1);
- list.append(bucket);
+ if (bucket)
+ list.append(bucket);
}
}
}
@@ -319,6 +329,9 @@ void PictureSet::splitAdd(const SkIRect& rect)
for (int i = firstTileX; i <= lastTileX; i++) {
for (int j = firstTileY; j <= lastTileY; j++) {
Bucket* bucket = getBucket(i, j);
+ if (!bucket)
+ continue;
+
SkIRect newRect;
int deltaX = i * maxSize;
int deltaY = j * maxSize;
@@ -442,8 +455,10 @@ void PictureSet::add(const SkRegion& area, SkPicture* picture,
Pictures pictureAndBounds = {collect, 0, collect.getBounds(),
elapsed, split, false, false, empty};
+#ifdef FAST_PICTURESET
if (mPictures.size() == 0)
checkForNewBases = true;
+#endif
mPictures.append(pictureAndBounds);
mAdditionalArea += totalArea.width() * totalArea.height();