diff options
12 files changed, 266 insertions, 81 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/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/ClassTracker.cpp index ad2b4dd..92d406c 100644 --- a/Source/WebCore/platform/graphics/android/ClassTracker.cpp +++ b/Source/WebCore/platform/graphics/android/ClassTracker.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "ClassTracker.h" +#include "LayerAndroid.h" + #include <cutils/log.h> #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> @@ -46,6 +48,7 @@ ClassTracker* ClassTracker::gInstance = 0; void ClassTracker::increment(String name) { + android::Mutex::Autolock lock(m_lock); int value = 0; if (m_classes.contains(name)) value = m_classes.get(name); @@ -55,6 +58,7 @@ void ClassTracker::increment(String name) void ClassTracker::decrement(String name) { + android::Mutex::Autolock lock(m_lock); int value = 0; if (m_classes.contains(name)) value = m_classes.get(name); @@ -62,13 +66,38 @@ void ClassTracker::decrement(String name) m_classes.set(name, value - 1); } + +void ClassTracker::add(LayerAndroid* layer) +{ + android::Mutex::Autolock lock(m_lock); + m_layers.append(layer); +} + +void ClassTracker::remove(LayerAndroid* layer) +{ + android::Mutex::Autolock lock(m_lock); + m_layers.remove(m_layers.find(layer)); +} + void ClassTracker::show() { + android::Mutex::Autolock lock(m_lock); XLOG("*** Tracking %d classes ***", m_classes.size()); for (HashMap<String, int>::iterator iter = m_classes.begin(); iter != m_classes.end(); ++iter) { XLOG("class %s has %d instances", iter->first.latin1().data(), iter->second); } + XLOG("*** %d Layers ***", m_layers.size()); + for (unsigned int i = 0; i < m_layers.size(); i++) { + LayerAndroid* layer = m_layers[i]; + XLOG("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x", + i, m_layers.size(), layer, + layer->getWidth(), layer->getHeight(), + layer->type(), layer->getRefCnt(), + layer->texture(), layer->imageRef(), + layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(), + (LayerAndroid*) layer->getParent()); + } } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.h b/Source/WebCore/platform/graphics/android/ClassTracker.h index e338cbd..d169883 100644 --- a/Source/WebCore/platform/graphics/android/ClassTracker.h +++ b/Source/WebCore/platform/graphics/android/ClassTracker.h @@ -26,6 +26,7 @@ #ifndef ClassTracker_h #define ClassTracker_h +#include <utils/threads.h> #include <wtf/HashMap.h> #include <wtf/text/StringHash.h> @@ -34,16 +35,22 @@ namespace WebCore { +class LayerAndroid; + class ClassTracker { public: static ClassTracker* instance(); void show(); void increment(String name); void decrement(String name); + void add(LayerAndroid*); + void remove(LayerAndroid*); private: ClassTracker() {}; HashMap<String, int> m_classes; + Vector<LayerAndroid*> m_layers; static ClassTracker* gInstance; + android::Mutex m_lock; }; } diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 2f3613b..85fa23f 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -659,6 +659,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, SkSafeUnref(baseLayer); #ifdef DEBUG TilesManager::instance()->getTilesTracker()->showTrackTextures(); + TilesManager::instance()->showImages(); #endif return ret; } diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index b8db80b..b086c79 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -73,7 +73,8 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_requestSent(false), m_scale(1), m_lastComputeTextureSize(0), - m_owningLayer(owner) + m_owningLayer(owner), + m_type(LayerAndroid::WebCoreLayer) { m_backgroundColor = 0; @@ -83,6 +84,7 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_dirtyRegion.setEmpty(); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid"); + ClassTracker::instance()->add(this); #endif } @@ -94,7 +96,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_texture(0), m_imageTexture(0), m_requestSent(false), - m_owningLayer(layer.m_owningLayer) + m_owningLayer(layer.m_owningLayer), + m_type(LayerAndroid::UILayer) { m_isFixed = layer.m_isFixed; m_imageRef = layer.m_imageRef; @@ -139,7 +142,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), } #ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid"); + ClassTracker::instance()->increment("LayerAndroid - recopy (UI?)"); + ClassTracker::instance()->add(this); #endif } @@ -156,7 +160,8 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_requestSent(false), m_scale(1), m_lastComputeTextureSize(0), - m_owningLayer(0) + m_owningLayer(0), + m_type(LayerAndroid::NavCacheLayer) { m_backgroundColor = 0; m_dirty = false; @@ -164,7 +169,8 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_iframeOffset.set(0,0); m_dirtyRegion.setEmpty(); #ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerAndroid"); + ClassTracker::instance()->increment("LayerAndroid - from picture"); + ClassTracker::instance()->add(this); #endif } @@ -176,7 +182,13 @@ LayerAndroid::~LayerAndroid() SkSafeUnref(m_recordingPicture); m_animations.clear(); #ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("LayerAndroid"); + ClassTracker::instance()->remove(this); + if (m_type == LayerAndroid::WebCoreLayer) + ClassTracker::instance()->decrement("LayerAndroid"); + else if (m_type == LayerAndroid::UILayer) + ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)"); + else if (m_type == LayerAndroid::NavCacheLayer) + ClassTracker::instance()->decrement("LayerAndroid - from picture"); #endif } diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index d6bb497..4ae8bd3 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -100,6 +100,7 @@ class PaintedSurface; class LayerAndroid : public Layer { public: + enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer }; LayerAndroid(RenderLayer* owner); LayerAndroid(const LayerAndroid& layer); LayerAndroid(SkPicture*); @@ -272,6 +273,10 @@ public: void assignTextureTo(LayerAndroid* newTree); void createTexture(); + SkBitmapRef* imageRef() { return m_imageRef; } + ImageTexture* imageTexture() { return m_imageTexture; } + int type() { return m_type; } + protected: virtual void onDraw(SkCanvas*, SkScalar opacity); @@ -379,7 +384,7 @@ private: RenderLayer* m_owningLayer; GLWebViewState* m_state; - + int m_type; typedef Layer INHERITED; }; 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..e100838 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) { @@ -173,9 +174,6 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, 0); } GLUtils::checkEglError("CreateSyncKHR"); - // Clean up FBO setup. - glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO - GLUtils::checkGlError("copy the surface texture into the normal one"); } @@ -260,8 +258,6 @@ void TransferQueue::discardQueue() // Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture. void TransferQueue::updateDirtyBaseTiles() { - if (m_currentUploadType == GpuUpload) - saveGLState(); android::Mutex::Autolock lock(m_transferQueueItemLocks); cleanupTransportQueue(); @@ -272,6 +268,7 @@ void TransferQueue::updateDirtyBaseTiles() // the texture and blit that into each BaseTile's texture. const int nextItemIndex = getNextTransferQueueIndex(); int index = nextItemIndex; + bool usedFboForUpload = false; for (int k = 0; k < ST_BUFFER_NUMBER ; k++) { if (m_transferQueue[index].status == pendingBlit) { bool obsoleteBaseTile = checkObsolete(index); @@ -298,6 +295,10 @@ void TransferQueue::updateDirtyBaseTiles() GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0, *m_transferQueue[index].bitmap); } else { + if (!usedFboForUpload) { + saveGLState(); + usedFboForUpload = true; + } blitTileFromQueue(m_fboID, destTexture, m_sharedSurfaceTextureId, m_sharedSurfaceTexture->getCurrentTextureTarget(), @@ -320,8 +321,13 @@ void TransferQueue::updateDirtyBaseTiles() index = (index + 1) % ST_BUFFER_NUMBER; } - if (m_currentUploadType == GpuUpload) + // Clean up FBO setup. Doing this for both CPU/GPU upload can make the + // dynamic switch possible. Moving this out from the loop can save some + // milli-seconds. + if (usedFboForUpload) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO restoreGLState(); + } m_emptyItemCount = ST_BUFFER_NUMBER; m_transferQueueItemCond.signal(); @@ -461,7 +467,9 @@ void TransferQueue::saveGLState() glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport); glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor); glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth); +#if DEBUG glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor); +#endif } void TransferQueue::setGLStateForCopy(int width, int height) @@ -470,9 +478,11 @@ void TransferQueue::setGLStateForCopy(int width, int height) glViewport(0, 0, width, height); glDisable(GL_SCISSOR_TEST); glDisable(GL_DEPTH_TEST); - + // Clear the content is only for debug purpose. +#if DEBUG glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); +#endif } void TransferQueue::restoreGLState() @@ -487,11 +497,12 @@ void TransferQueue::restoreGLState() if (m_GLStateBeforeBlit.depth[0]) glEnable(GL_DEPTH_TEST); - +#if DEBUG glClearColor(m_GLStateBeforeBlit.clearColor[0], m_GLStateBeforeBlit.clearColor[1], m_GLStateBeforeBlit.clearColor[2], m_GLStateBeforeBlit.clearColor[3]); +#endif } int TransferQueue::getNextTransferQueueIndex() |
