summaryrefslogtreecommitdiffstats
path: root/Source/WebCore
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2011-09-29 16:44:59 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-09-29 16:44:59 -0700
commit70766d2b423da8555553b35dba98bad79529b97c (patch)
tree9cbf40bdac53da71c19334a124ecc759c16639ed /Source/WebCore
parent661b2b2086b75ea8e548673e83210226e46cd49d (diff)
parentf6a40880028cf495025747229c627f42e25acc66 (diff)
downloadexternal_webkit-70766d2b423da8555553b35dba98bad79529b97c.zip
external_webkit-70766d2b423da8555553b35dba98bad79529b97c.tar.gz
external_webkit-70766d2b423da8555553b35dba98bad79529b97c.tar.bz2
Merge "Use state machine to track tile state"
Diffstat (limited to 'Source/WebCore')
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.cpp137
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.h58
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTileTexture.cpp22
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.cpp28
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.h2
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp1
7 files changed, 187 insertions, 66 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp
index a4ce788..4a15f9f 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp
@@ -70,8 +70,8 @@ BaseTile::BaseTile(bool isLayerTile)
, m_lastDirtyPicture(0)
, m_isTexturePainted(false)
, m_isLayerTile(isLayerTile)
- , m_swapDrawCount(0)
, m_drawCount(0)
+ , m_state(Unpainted)
{
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("BaseTile");
@@ -113,13 +113,15 @@ BaseTile::~BaseTile()
void BaseTile::setContents(TilePainter* painter, int x, int y, float scale)
{
- android::AutoMutex lock(m_atomicSync);
if ((m_painter != painter)
|| (m_x != x)
|| (m_y != y)
- || (m_scale != scale))
- fullInval();
+ || (m_scale != scale)) {
+ // neither texture is relevant
+ discardTextures();
+ }
+ android::AutoMutex lock(m_atomicSync);
m_painter = painter;
m_x = x;
m_y = y;
@@ -133,14 +135,15 @@ void BaseTile::reserveTexture()
android::AutoMutex lock(m_atomicSync);
if (texture && m_backTexture != texture) {
- m_swapDrawCount = 0; // no longer ready to swap
+ m_state = Unpainted;
m_backTexture = texture;
}
- // a texture reservation will only happen if we're dirty, or ready to
- // swap. if it's the former, ensure it's marked dirty.
- if (!m_swapDrawCount)
+ if (m_state == UpToDate) {
+ XLOG("moving tile %p to unpainted, since it reserved while up to date", this);
m_dirty = true;
+ m_state = Unpainted;
+ }
}
bool BaseTile::removeTexture(BaseTileTexture* texture)
@@ -149,10 +152,18 @@ bool BaseTile::removeTexture(BaseTileTexture* texture)
this, m_backTexture, m_frontTexture, m_page);
// We update atomically, so paintBitmap() can see the correct value
android::AutoMutex lock(m_atomicSync);
- if (m_frontTexture == texture)
+ if (m_frontTexture == texture) {
+ if (m_state == UpToDate) {
+ XLOG("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture);
+ m_state = Unpainted;
+ }
+
m_frontTexture = 0;
- if (m_backTexture == texture)
+ }
+ if (m_backTexture == texture) {
+ m_state = Unpainted;
m_backTexture = 0;
+ }
// mark dirty regardless of which texture was taken - the back texture may
// have been ready to swap
@@ -161,15 +172,6 @@ bool BaseTile::removeTexture(BaseTileTexture* texture)
return true;
}
-void BaseTile::fullInval()
-{
- for (int i = 0; i < m_maxBufferNumber; i++) {
- m_dirtyArea[i].setEmpty();
- m_fullRepaint[i] = true;
- }
- m_dirty = true;
-}
-
void BaseTile::markAsDirty(int unsigned pictureCount,
const SkRegion& dirtyArea)
{
@@ -180,6 +182,20 @@ void BaseTile::markAsDirty(int unsigned pictureCount,
for (int i = 0; i < m_maxBufferNumber; i++)
m_dirtyArea[i].op(dirtyArea, SkRegion::kUnion_Op);
m_dirty = true;
+ if (m_state == UpToDate) {
+ // We only mark a tile as unpainted in 'markAsDirty' if its status is
+ // UpToDate: marking dirty means we need to repaint, but don't stop the
+ // current paint
+ m_state = Unpainted;
+ } else if (m_state != Unpainted) {
+ // layer tiles and prefetch page tiles are potentially marked dirty
+ // while in the process of painting, due to not using an update lock
+
+ // TODO: fix it so that they can paint while deferring the markAsDirty
+ // call (or block updates)
+ XLOG("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d, page %p",
+ this, m_x, m_y, isLayerTile(), m_state, m_page);
+ }
}
bool BaseTile::isDirty()
@@ -232,8 +248,9 @@ void BaseTile::draw(float transparency, SkRect& rect, float scale)
else
TilesManager::instance()->shader()->drawQuad(rect, m_frontTexture->m_ownTextureId,
transparency);
- } else
- m_dirty = true;
+ } else {
+ XLOG("tile %p at %d, %d not readyfor (at draw),", this, m_x, m_y);
+ }
m_frontTexture->consumerRelease();
}
@@ -242,7 +259,7 @@ bool BaseTile::isTileReady()
{
// Return true if the tile's most recently drawn texture is up to date
android::AutoMutex lock(m_atomicSync);
- BaseTileTexture * texture = m_swapDrawCount ? m_backTexture : m_frontTexture;
+ BaseTileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture;
if (!texture)
return false;
@@ -253,6 +270,9 @@ bool BaseTile::isTileReady()
if (m_dirty)
return false;
+ if (m_state != ReadyToSwap && m_state != UpToDate)
+ return false;
+
texture->consumerLock();
bool ready = texture->readyFor(this);
texture->consumerRelease();
@@ -260,7 +280,8 @@ bool BaseTile::isTileReady()
if (ready)
return true;
- m_dirty = true;
+ XLOG("tile %p at %d, %d not readyfor (at isTileReady)", this, m_x, m_y);
+
return false;
}
@@ -303,6 +324,11 @@ void BaseTile::paintBitmap()
m_atomicSync.unlock();
return;
}
+ if (m_state != Unpainted) {
+ XLOG("Warning: started painting tile %p, but was at state %d, ft %p bt %p",
+ this, m_state, m_frontTexture, m_backTexture);
+ }
+ m_state = PaintingStarted;
texture->producerAcquireContext();
TextureInfo* textureInfo = texture->producerLock();
@@ -439,11 +465,10 @@ void BaseTile::paintBitmap()
XLOG("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty);
- if (!m_dirty) {
- // swap textures, but WAIT until the next draw call (since we need
- // to let GLWebViewState blit them at the beginning of drawGL)
- m_swapDrawCount = TilesManager::instance()->getDrawGLCount() + 1;
- }
+ validatePaint();
+ } else {
+ XLOG("tile %p no longer owns texture %p, m_state %d. ft %p bt %p",
+ this, texture, m_state, m_frontTexture, m_backTexture);
}
m_atomicSync.unlock();
@@ -459,27 +484,73 @@ void BaseTile::discardTextures() {
m_backTexture->release(this);
m_backTexture = 0;
}
+ for (int i = 0; i < m_maxBufferNumber; i++) {
+ m_dirtyArea[i].setEmpty();
+ m_fullRepaint[i] = true;
+ }
m_dirty = true;
+ m_state = Unpainted;
}
bool BaseTile::swapTexturesIfNeeded() {
android::AutoMutex lock(m_atomicSync);
- if (m_swapDrawCount && TilesManager::instance()->getDrawGLCount() >= m_swapDrawCount) {
+ if (m_state == ReadyToSwap) {
// 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_swapDrawCount = 0;
- XLOG("display texture for %d, %d front is now %p, texture is %p",
- m_x, m_y, m_frontTexture, m_backTexture);
+ m_state = UpToDate;
+ XLOG("display texture for %p at %d, %d front is now %p, back is %p",
+ this, m_x, m_y, m_frontTexture, m_backTexture);
+
return true;
}
return false;
}
+void BaseTile::backTextureTransfer() {
+ android::AutoMutex lock(m_atomicSync);
+ if (m_state == PaintingStarted)
+ m_state = TransferredUnvalidated;
+ else if (m_state == ValidatedUntransferred)
+ m_state = ReadyToSwap;
+ else {
+ // shouldn't have transferred a tile in any other state, log
+ XLOG("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d",
+ this, m_x, m_y, m_state);
+ }
+}
+
+void BaseTile::validatePaint() {
+ // ONLY CALL while m_atomicSync is locked (at the end of paintBitmap())
+
+ if (!m_dirty) {
+ // since after the paint, the tile isn't dirty, 'validate' it - this
+ // may happed before or after the transfer queue operation. Only
+ // when both have happened, mark as 'ReadyToSwap'
+ if (m_state == PaintingStarted)
+ m_state = ValidatedUntransferred;
+ else if (m_state == TransferredUnvalidated)
+ m_state = ReadyToSwap;
+ else {
+ // shouldn't have just finished painting in any other state, log
+ XLOG("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d",
+ this, m_x, m_y, m_state);
+ }
+
+ if (m_deferredDirty) {
+ XLOG("Note: deferred dirty flag set, possibly a missed paint on tile %p", this);
+ m_deferredDirty = false;
+ }
+ } else {
+ XLOG("Note: paint was unsuccessful.");
+ m_state = Unpainted;
+ }
+
+}
+
} // 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 734a3c8..6d0fa8f 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.h
+++ b/Source/WebCore/platform/graphics/android/BaseTile.h
@@ -61,6 +61,34 @@ class GLWebViewState;
*/
class BaseTile : public TextureOwner {
public:
+
+ // eventually, m_dirty might be rolled into the state machine, but note
+ // that a tile that's continually marked dirty from animation should still
+ // progress through the state machine and be drawn periodically (esp. for
+ // layers)
+
+ // /-> TransferredUnvalidated (TQ interrupts paint) -\ (TQ & paint done)
+ // Unpainted -> PaintingStarted -- -> ReadyToSwap -> UpToDate
+ // ^ \-> ValidatedUntransferred (paint finish before TQ) -/
+ // |
+ // \--... (From any state when marked dirty. should usually come from UpToDate if the updates are locked)
+ //
+
+ enum TextureState{
+ // back texture is completely unpainted
+ Unpainted = 0,
+ // has started painting, but haven't been transferred or validated
+ PaintingStarted = 1,
+ // back texture painted, transferred before validating in PaintBitmap()
+ TransferredUnvalidated = 2,
+ // back texture painted, validated before transferring in TransferQueue
+ ValidatedUntransferred = 3,
+ // back texture has been blitted, will be swapped when next available
+ ReadyToSwap = 4,
+ // has been swapped, is ready to draw, all is well
+ UpToDate = 5,
+ };
+
BaseTile(bool isLayerTile = false);
~BaseTile();
@@ -88,15 +116,18 @@ public:
bool isRepaintPending();
void setRepaintPending(bool pending);
float scale() const { return m_scale; }
- void fullInval();
+ TextureState textureState() const { return m_state; }
int x() const { return m_x; }
int y() const { return m_y; }
BaseTileTexture* frontTexture() { return m_frontTexture; }
BaseTileTexture* backTexture() { return m_backTexture; }
+
+ // only used for prioritization - the higher, the more relevant the tile is
+ unsigned long long drawCount() { return m_drawCount; }
void discardTextures();
bool swapTexturesIfNeeded();
- unsigned long long drawCount() { return m_drawCount; }
+ void backTextureTransfer();
void setGLWebViewState(GLWebViewState* state) { m_glWebViewState = state; }
@@ -107,6 +138,8 @@ public:
TilePainter* painter() { return m_painter; }
private:
+ void validatePaint();
+
GLWebViewState* m_glWebViewState;
TilePainter* m_painter;
@@ -124,6 +157,10 @@ private:
// used to signal that the that the tile is out-of-date and needs to be
// redrawn in the backTexture
bool m_dirty;
+
+ // currently only for debugging, to be used for tracking down dropped repaints
+ bool m_deferredDirty;
+
// used to signal that a repaint is pending
bool m_repaintPending;
// stores the id of the latest picture from webkit that caused this tile to
@@ -149,18 +186,19 @@ private:
bool m_isLayerTile;
- // this is set when the back texture is finished painting and should be
- // swapped to the front. it is set with the NEXT drawGL call (see
- // TilesManager::m_drawGLCount) so that the textures may be blitted at the
- // beginning of GLWebViewState::drawGL before they are swapped
-
- // 4 steps for texture: paint -> blit -> swap -> draw
- unsigned long long m_swapDrawCount;
-
// 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;
+
+ // Tracks the state of painting for the tile. High level overview:
+ // 1) Unpainted - until paint starts (and if marked dirty, in most cases)
+ // 2) PaintingStarted - until paint completes
+ // 3) TransferredUnvalidated - if transferred first
+ // or ValidatedUntransferred - if validated first
+ // 4) ReadyToSwap - if painted and transferred, but not swapped
+ // 5) UpToDate - until marked dirty again
+ TextureState m_state;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
index d60d695..54c96c8 100644
--- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
@@ -32,11 +32,14 @@
#include "GLUtils.h"
#include "TilesManager.h"
-#ifdef DEBUG
-
#include <cutils/log.h>
#include <wtf/text/CString.h>
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
+
+#ifdef DEBUG
+
#undef XLOG
#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
@@ -89,7 +92,12 @@ void BaseTileTexture::discardTexture()
{
if (m_ownTextureId)
GLUtils::deleteTexture(&m_ownTextureId);
- release(m_owner);
+
+ if (m_owner) {
+ // clear both Tile->Texture and Texture->Tile links
+ m_owner->removeTexture(this);
+ release(m_owner);
+ }
}
void BaseTileTexture::destroyTextures(SharedTexture** textures)
@@ -227,9 +235,6 @@ bool BaseTileTexture::release(TextureOwner* owner)
if (m_owner != owner)
return false;
- // force readyFor to return false next call (even if texture reaquired by same tile)
- m_ownTextureTileInfo.m_x = -1;
- m_ownTextureTileInfo.m_y = -1;
if (!m_busy) {
m_owner = 0;
} else {
@@ -271,6 +276,11 @@ void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info
m_ownTextureTileInfo.m_painter = info->m_painter;
m_ownTextureTileInfo.m_picture = info->m_picture;
m_ownTextureTileInfo.m_inverted = TilesManager::instance()->invertedScreen();
+ if (m_owner) {
+ BaseTile* owner = static_cast<BaseTile*>(m_owner);
+ owner->backTextureTransfer();
+ }
+
}
bool BaseTileTexture::readyFor(BaseTile* baseTile)
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp
index 0c7a2a8..34f0d4e 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp
@@ -300,6 +300,7 @@ bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale, SwapM
return false;
int swaps = 0;
+ bool fullSwap = true;
if (swap == SwapWholePage) {
for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
@@ -308,31 +309,26 @@ bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale, SwapM
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;
}
+
+ // swap every tile on page (even if off screen)
+ for (int j = 0; j < m_baseTileSize; j++) {
+ BaseTile& tile = m_baseTiles[j];
+ if (tile.swapTexturesIfNeeded())
+ swaps++;
+ }
+
+ XLOG("%p %s swapped %d textures, returning true",
+ this, (swap == SwapWholePage) ? "whole page" : "greedy swap", swaps);
+ return fullSwap;
}
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h
index c903abc..780a604 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.h
+++ b/Source/WebCore/platform/graphics/android/TiledPage.h
@@ -91,6 +91,8 @@ public:
GLWebViewState* glWebViewState() { return m_glWebViewState; }
float scale() const { return m_scale; }
+
+ //TODO: clear all textures if this is called with a new value
void setScale(float scale) { m_scale = scale; m_invScale = 1 / scale; }
void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount);
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp
index c7e6c5a..cf66de5 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp
@@ -314,9 +314,12 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner)
BaseTile* previousOwner = static_cast<BaseTile*>(farthestTexture->owner());
if (farthestTexture->acquire(owner)) {
if (previousOwner) {
- XLOG("%s texture %p stolen from tile %d, %d, drawCount was %llu (current is %llu)",
+ previousOwner->removeTexture(farthestTexture);
+
+ XLOG("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)",
owner->isLayerTile() ? "LAYER" : "BASE",
farthestTexture, previousOwner->x(), previousOwner->y(),
+ owner->x(), owner->y(),
oldestDrawCount, getDrawGLCount());
}
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
index fa7f5b6..a6b2e26 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -60,6 +60,7 @@ TransferQueue::TransferQueue()
, m_fboID(0)
, m_sharedSurfaceTextureId(0)
, m_hasGLContext(true)
+ , m_interruptedByRemovingOp(false)
, m_currentDisplay(EGL_NO_DISPLAY)
, m_currentUploadType(DEFAULT_UPLOAD_TYPE)
{