android::AutoMutex lock(m_atomicSync);
if (texture && m_backTexture != texture) {
+ XLOG("tile %p reserving texture %p, back was %p (front %p)",
+ this, texture, m_backTexture, m_frontTexture);
m_state = Unpainted;
m_backTexture = texture;
}
bool BaseTile::removeTexture(BaseTileTexture* texture)
{
- XLOG("%x removeTexture back %x front %x... page %x",
- this, m_backTexture, m_frontTexture, m_page);
+ XLOG("%p removeTexture %p, back %p front %p... page %p",
+ this, texture, 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) {
void BaseTile::discardTextures() {
android::AutoMutex lock(m_atomicSync);
+ XLOG("%p discarding bt %p, ft %p",
+ this, m_backTexture, m_frontTexture);
if (m_frontTexture) {
m_frontTexture->release(this);
m_frontTexture = 0;
#endif
}
-void BaseTileTexture::requireTexture()
+void BaseTileTexture::requireGLTexture()
{
if (!m_ownTextureId)
m_ownTextureId = GLUtils::createBaseTileGLTexture(m_size.width(), m_size.height());
}
-void BaseTileTexture::discardTexture()
+void BaseTileTexture::discardGLTexture()
{
if (m_ownTextureId)
GLUtils::deleteTexture(&m_ownTextureId);
- if (m_owner) {
- // clear both Tile->Texture and Texture->Tile links
- m_owner->removeTexture(this);
- release(m_owner);
- }
+ releaseAndRemoveFromTile();
}
void BaseTileTexture::destroyTextures(SharedTexture** textures)
return setOwner(owner, force);
}
-bool BaseTileTexture::tryAcquire(TextureOwner* owner)
-{
- m_busyLock.lock();
- if (!m_busy
- && m_owner
- && m_owner->state() != owner->state()) {
- m_busyLock.unlock();
- return this->acquire(owner);
- }
- m_busyLock.unlock();
- return false;
-}
-
bool BaseTileTexture::setOwner(TextureOwner* owner, bool force)
{
// if the writable texture is busy (i.e. currently being written to) then we
bool BaseTileTexture::release(TextureOwner* owner)
{
android::Mutex::Autolock lock(m_busyLock);
+ XLOG("texture %p releasing tile %p, m_owner %p, m_busy %d", this, owner, m_owner, m_busy);
if (m_owner != owner)
return false;
return true;
}
+void BaseTileTexture::releaseAndRemoveFromTile()
+{
+ if (m_owner) {
+ // clear both Tile->Texture and Texture->Tile links
+ m_owner->removeTexture(this);
+ release(m_owner);
+ }
+}
+
void BaseTileTexture::setTile(TextureInfo* info, int x, int y,
float scale, TilePainter* painter,
unsigned int pictureCount)
// returns false if ownership cannot be transferred because the tile is busy
bool acquire(TextureOwner* owner, bool force = false);
bool release(TextureOwner* owner);
- bool tryAcquire(TextureOwner* owner);
+
+ // removes Tile->Texture, and Texture->Tile links to fully discard the texture
+ void releaseAndRemoveFromTile();
// set the texture owner if not busy. Return false if busy, true otherwise.
bool setOwner(TextureOwner* owner, bool force = false);
// OpenGL ID of backing texture, 0 when not allocated
GLuint m_ownTextureId;
// these are used for dynamically (de)allocating backing graphics memory
- void requireTexture();
- void discardTexture();
+ void requireGLTexture();
+ void discardGLTexture();
void setOwnTextureTileInfoFromQueue(const TextureTileInfo* info);
m_currentPictureCounter++;
if (!rect.isEmpty()) {
// find which tiles fall within the invalRect and mark them as dirty
- frontPage()->invalidateRect(rect, m_currentPictureCounter);
+ m_tiledPageA->invalidateRect(rect, m_currentPictureCounter);
+ m_tiledPageB->invalidateRect(rect, m_currentPictureCounter);
if (m_frameworkInval.isEmpty())
m_frameworkInval = rect;
else
for (unsigned int i = 0; i < max; i++) {
TextureOwner* owner = m_textures[i]->owner();
if (!owner || owner->drawCount() < sparedDrawCount) {
- m_textures[i]->discardTexture();
+ m_textures[i]->discardGLTexture();
dealloc++;
}
}
for (unsigned int i = 0; i < maxLayer; i++) {
TextureOwner* owner = m_tilesTextures[i]->owner();
if (!owner || owner->drawCount() < sparedDrawCount) {
- m_tilesTextures[i]->discardTexture();
+ m_tilesTextures[i]->discardGLTexture();
dealloc++;
}
}
}
// guarantee that we have a texture to blit into
- destTexture->requireTexture();
+ destTexture->requireGLTexture();
if (m_transferQueue[index].uploadType == CpuUpload) {
// Here we just need to upload the bitmap content to the GL Texture
void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
int x, int y, const SkBitmap& bitmap)
{
+ if (!tryUpdateQueueWithBitmap(renderInfo, x, y, bitmap)) {
+ // failed placing bitmap in queue, discard tile's texture so it will be
+ // re-enqueued (and repainted)
+ BaseTile* tile = renderInfo->baseTile;
+ if (tile) {
+ BaseTileTexture* texture = tile->backTexture();
+ if (texture)
+ texture->releaseAndRemoveFromTile();
+ }
+ }
+}
+
+bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
+ int x, int y, const SkBitmap& bitmap)
+{
m_transferQueueItemLocks.lock();
bool ready = readyForUpdate();
TextureUploadType currentUploadType = m_currentUploadType;
if (!ready) {
XLOG("Quit bitmap update: not ready! for tile x y %d %d",
renderInfo->x, renderInfo->y);
- return;
+ return false;
}
if (currentUploadType == GpuUpload) {
// a) Dequeue the Surface Texture and write into the buffer
if (!m_ANW.get()) {
XLOG("ERROR: ANW is null");
- return;
+ return false;
}
ANativeWindow_Buffer buffer;
if (ANativeWindow_lock(m_ANW.get(), &buffer, 0))
- return;
+ return false;
uint8_t* img = (uint8_t*)buffer.bits;
int row, col;
m_transferQueueItemLocks.unlock();
XLOG("Bitmap updated x, y %d %d, baseTile %p",
renderInfo->x, renderInfo->y, renderInfo->baseTile);
+ return true;
}
// Note that there should be lock/unlock around this function call.
// be called to keep things in sync.
if (m_transferQueue[index].uploadType == GpuUpload)
m_sharedSurfaceTexture->updateTexImage();
+
+ // since tiles in the queue may be from another webview, remove
+ // their textures so that they will be repainted / retransferred
+ BaseTile* tile = m_transferQueue[index].savedBaseTilePtr;
+ if (tile) {
+ BaseTileTexture* texture = tile->backTexture();
+ if (texture)
+ texture->releaseAndRemoveFromTile();
+ }
+ XLOG("transfer queue discarded tile %p, removed texture", tile);
+
m_transferQueue[index].savedBaseTilePtr = 0;
m_transferQueue[index].status = emptyItem;
}
void initSharedSurfaceTextures(int width, int height);
+ // insert the bitmap into the queue, mark the tile dirty if failing
void updateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y,
const SkBitmap& bitmap);
EGLSurface m_eglSurface;
private:
+ // return true if successfully inserted into queue
+ bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y,
+ const SkBitmap& bitmap);
bool getHasGLContext();
void setHasGLContext(bool hasContext);