diff options
Diffstat (limited to 'WebCore/platform/graphics/android/TilesManager.cpp')
-rw-r--r-- | WebCore/platform/graphics/android/TilesManager.cpp | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp new file mode 100644 index 0000000..a600f39 --- /dev/null +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -0,0 +1,254 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "TilesManager.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseTile.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +#ifdef DEBUG + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +// Important: We need at least twice as much textures as is needed to cover +// one viewport, otherwise the allocation may stall. +// We need n textures for one TiledPage, and another n textures for the +// second page used when scaling. +// In our case, we use 300x300 textures. On the tablet, this equals to +// at least 24 (6 * 4) textures, hence 48. +#define DEFAULT_TEXTURES_ALLOCATION 48 +#define DEFAULT_TEXTURE_SIZE_WIDTH 300 +#define DEFAULT_TEXTURE_SIZE_HEIGHT 300 + +namespace WebCore { + +TilesManager::TilesManager() + : m_generatorReady(false) +{ + m_textures.reserveCapacity(DEFAULT_TEXTURES_ALLOCATION); + for (int i = 0; i < DEFAULT_TEXTURES_ALLOCATION; i++) { + BackedDoubleBufferedTexture* texture = new BackedDoubleBufferedTexture( + tileWidth(), tileHeight()); + m_textures.append(texture); + } + + m_pixmapsGenerationThread = new TexturesGenerator(); + m_pixmapsGenerationThread->run("TexturesGenerator"); +} + +// Has to be run on the texture generation threads +void TilesManager::enableTextures() +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i < m_textures.size(); i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + texture->producerAcquireContext(); + } +} + +void TilesManager::printTextures() +{ +#ifdef DEBUG + XLOG("++++++"); + for (unsigned int i = 0; i < m_textures.size(); i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + BaseTile* o = 0; + if (texture->owner()) + o = (BaseTile*) texture->owner(); + int x = -1; + int y = -1; + if (o) { + x = o->x(); + y = o->y(); + } + XLOG("[%d] texture %x (picture: %d) usedLevel: %d busy: %d owner: %x (%d, %d) page: %x scale: %.2f", + i, texture, texture->pictureUsed(), texture->usedLevel(), + texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0); + } + XLOG("------"); +#endif // DEBUG +} + +void TilesManager::paintTexturesDefault() +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i < m_textures.size(); i++) { + for (int j = 0; j < 2; j++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + TextureInfo* textureInfo = texture->producerLock(); + SkCanvas* canvas = texture->canvas(); +#ifdef DEBUG + if (j) + canvas->drawARGB(255, 0, 0, 255); + else + canvas->drawARGB(255, 255, 0, 255); + SkPaint paint; + paint.setARGB(128, 255, 0, 0); + paint.setStrokeWidth(3); + canvas->drawLine(0, 0, tileWidth(), tileHeight(), paint); + paint.setARGB(128, 0, 255, 0); + canvas->drawLine(0, tileHeight(), tileWidth(), 0, paint); + paint.setARGB(128, 0, 0, 255); + canvas->drawLine(0, 0, tileWidth(), 0, paint); + canvas->drawLine(tileWidth(), 0, tileWidth(), tileHeight(), paint); +#else + canvas->drawARGB(255, 255, 255, 255); +#endif // DEBUG + PaintingInfo info; + texture->update(textureInfo, info); + texture->producerRelease(); + } + } +} + +void TilesManager::resetTextureUsage(TiledPage* page) +{ + android::Mutex::Autolock lock(m_texturesLock); + for (unsigned int i = 0; i < m_textures.size(); i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->owner()) { + if (texture->owner()->page() == page) + texture->setUsedLevel(-1); + } + } +} + +BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner) +{ + android::Mutex::Autolock lock(m_texturesLock); + unsigned int max = m_textures.size(); + // First see if we have something already painted for this tile + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->painter() == owner) { + if (texture->acquire(owner)) { + texture->setUsedLevel(0); + XLOG("same painter, getAvailableTexture(%x) => texture %x", owner, texture); + return texture; + } + } + } + // Then, let's return an owned texture if any + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->owner() == owner) { + texture->setUsedLevel(0); + XLOG("same owner, getAvailableTexture(%x) => texture %x", owner, texture); + return texture; + } + } + // Ok... at this point we need to decide which texture to grab + // The texture level indicates their closeness to the current viewport; + // let's just grab the texture that is as far as possible, or any + // texture that is unused. + BackedDoubleBufferedTexture* farthestTexture = 0; + int farthestTextureLevel = 0; + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->usedLevel() == -1) { // found an unused texture, grab it + farthestTexture = texture; + break; + } + if (farthestTextureLevel < texture->usedLevel()) { + farthestTextureLevel = texture->usedLevel(); + farthestTexture = texture; + } + } + if (farthestTexture && farthestTexture->acquire(owner)) { + farthestTexture->setUsedLevel(0); + XLOG("farthest texture, getAvailableTexture(%x) => texture %x (level %d)", + owner, farthestTexture, farthestTexture->usedLevel()); + return farthestTexture; + } + // At this point, all textures are used. Let's just grab one + // that is not ours... + // First, get the two tiled page associated to this, to be sure + // we won't starve ourselves + TiledPage* currentPage = owner->page(); + TiledPage* nextPage = currentPage->sibling(); + for (unsigned int i = 0; i < max; i++) { + BackedDoubleBufferedTexture* texture = m_textures[i]; + if (texture->owner() + && texture->owner()->page() != currentPage + && texture->owner()->page() != nextPage) { + if (texture->acquire(owner)) { + XLOG("grab a texture that wasn't ours, (%x != %x) at %d => texture %x", + owner->page(), texture->owner()->page(), i, texture); + texture->setUsedLevel(0); + return texture; + } + } + } + + XLOG("Couldn't find an available texture for BaseTile %x (%d, %d) !!!", + owner, owner->x(), owner->y()); +#ifdef DEBUG + printTextures(); +#endif // DEBUG + return 0; +} + +float TilesManager::tileWidth() const +{ + return DEFAULT_TEXTURE_SIZE_WIDTH; +} + +float TilesManager::tileHeight() const +{ + return DEFAULT_TEXTURE_SIZE_HEIGHT; +} + +TilesManager* TilesManager::instance() +{ + if (!gInstance) { + gInstance = new TilesManager(); + XLOG("Waiting for the generator..."); + gInstance->waitForGenerator(); + XLOG("Generator ready!"); + } + return gInstance; +} + +TilesManager* TilesManager::gInstance = 0; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) |