diff options
8 files changed, 155 insertions, 152 deletions
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp index 448be78..d4725f2 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -37,16 +37,16 @@ namespace WebCore { BackedDoubleBufferedTexture::BackedDoubleBufferedTexture(uint32_t w, uint32_t h, SkBitmap::Config config) - : DoubleBufferedTexture(eglGetCurrentContext()), - m_canvas(0), - m_width(0), - m_height(0), - m_usedLevel(-1), - m_owner(0), - m_painter(0), - m_busy(false) + : DoubleBufferedTexture(eglGetCurrentContext()) + , m_usedLevel(-1) + , m_owner(0) + , m_painter(0) + , m_busy(false) { - setBitmap(w, h, config); + m_bitmap.setConfig(config, w, h); + m_bitmap.allocPixels(); + m_bitmap.eraseColor(0); + m_canvas = new SkCanvas(m_bitmap); } BackedDoubleBufferedTexture::~BackedDoubleBufferedTexture() @@ -55,53 +55,55 @@ BackedDoubleBufferedTexture::~BackedDoubleBufferedTexture() delete m_canvas; } -void BackedDoubleBufferedTexture::setBitmap(uint32_t w, uint32_t h, SkBitmap::Config config) +TextureInfo* BackedDoubleBufferedTexture::producerLock() { - if ((m_width == w) && (m_height == h)) - return; - m_width = w; - m_height = h; - m_bitmap.reset(); - m_bitmap.setConfig(config, m_width, m_height); - m_bitmap.allocPixels(); - m_bitmap.eraseColor(0); - m_bitmap.eraseARGB(255, 255, 0, 0); - delete m_canvas; - m_canvas = new SkCanvas(m_bitmap); + m_varLock.lock(); + m_busy = true; + m_varLock.unlock(); + return DoubleBufferedTexture::producerLock(); } -void BackedDoubleBufferedTexture::update(TextureInfo* textureInfo, PaintingInfo& info) +void BackedDoubleBufferedTexture::producerRelease() { - if (!m_width && !m_height) + DoubleBufferedTexture::producerRelease(); + android::Mutex::Autolock lock(m_varLock); + m_busy = false; +} + +void BackedDoubleBufferedTexture::producerReleaseAndSwap() +{ + DoubleBufferedTexture::producerReleaseAndSwap(); + android::Mutex::Autolock lock(m_varLock); + m_busy = false; +} + +void BackedDoubleBufferedTexture::producerUpdate(BaseTile* painter, + TextureInfo* textureInfo, PaintingInfo& info) +{ + // no need to upload a texture since the bitmap is empty + if (!m_bitmap.width() && !m_bitmap.height()) { + producerRelease(); return; + } - if (textureInfo && textureInfo->m_textureId) { - if (textureInfo->m_width && textureInfo->m_height - && (m_width != textureInfo->m_width) - && (m_height != textureInfo->m_height)) { - GLUtils::deleteTexture(&textureInfo->m_textureId); - glGenTextures(1, &textureInfo->m_textureId); - textureInfo->m_width = 0; - textureInfo->m_height = 0; - } - - if (!textureInfo->m_width && !textureInfo->m_height) - GLUtils::createTextureWithBitmap(textureInfo->m_textureId, m_bitmap); - else - GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, m_bitmap); - - if ((m_width != textureInfo->m_width) - && (m_height != textureInfo->m_height)) { - textureInfo->m_width = m_width; - textureInfo->m_height = m_height; - } + if (textureInfo->m_width == m_bitmap.width() && textureInfo->m_height == m_bitmap.height()) + GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, m_bitmap); + else { + GLUtils::createTextureWithBitmap(textureInfo->m_textureId, m_bitmap); + textureInfo->m_width = m_bitmap.width(); + textureInfo->m_height = m_bitmap.height(); } + m_varLock.lock(); + m_painter = painter; + // set the painting information for this texture if (textureInfo->m_textureId == m_textureA.getSourceTextureId()) m_paintingInfoA = info; - if (textureInfo->m_textureId == m_textureB.getSourceTextureId()) + else if (textureInfo->m_textureId == m_textureB.getSourceTextureId()) m_paintingInfoB = info; m_varLock.unlock(); + + producerReleaseAndSwap(); } // Compare the current texture displayed with some PaintingInfo. @@ -121,44 +123,20 @@ bool BackedDoubleBufferedTexture::consumerTextureSimilar(PaintingInfo& info) return info.similar(m_paintingInfoB); } -void BackedDoubleBufferedTexture::setOwner(BaseTile* owner) -{ - android::Mutex::Autolock lock(m_varLock); - if (m_owner != owner) { - if (m_owner) - m_owner->removeTexture(); - m_owner = owner; - } -} - bool BackedDoubleBufferedTexture::acquire(BaseTile* owner) { + // if the writable texture is currently being written to we can't change the + // owner out from underneath that texture android::Mutex::Autolock lock(m_varLock); + if (m_owner == owner) + return true; if (m_busy) return false; - if (m_owner != owner) { - if (m_owner) - m_owner->removeTexture(); - m_owner = owner; - } + if (m_owner) + m_owner->removeTexture(); + m_owner = owner; return true; } -void BackedDoubleBufferedTexture::setPainter(BaseTile* painter) -{ - android::Mutex::Autolock lock(m_varLock); - m_painter = painter; -} - -bool BackedDoubleBufferedTexture::acquireForPainting() -{ - android::Mutex::Autolock lock(m_varLock); - if (!m_busy) { - m_busy = true; - return true; - } - return false; -} - } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h index 697a3ac..97c9d48 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h @@ -75,40 +75,46 @@ private: // DoubleBufferedTexture using a SkBitmap as backing mechanism class BackedDoubleBufferedTexture : public DoubleBufferedTexture { public: - // ctor called on consumer thread + // This object is to be constructed on the consumer's thread and must have + // a width and height greater than 0. BackedDoubleBufferedTexture(uint32_t w, uint32_t h, SkBitmap::Config config = SkBitmap::kARGB_8888_Config); virtual ~BackedDoubleBufferedTexture(); - void setBitmap(uint32_t w, uint32_t h, SkBitmap::Config config = SkBitmap::kARGB_8888_Config); - void update(TextureInfo* textureInfo, PaintingInfo& info); - SkCanvas* canvas() { return m_canvas; } + // these functions override their parent + virtual TextureInfo* producerLock(); + virtual void producerRelease(); + virtual void producerReleaseAndSwap(); + + // updates the texture with current bitmap and releases (and if needed also + // swaps) the texture. + void producerUpdate(BaseTile* painter, TextureInfo* textureInfo, PaintingInfo& info); - // Level can be -1 (unused texture), 0 (the 9 tiles intersecting with the - // viewport), then the distance between the viewport and the tile. - // we use this to prioritize which texture we want to pick (see - // TilesManager::getAvailableTexture()) - int usedLevel() { android::Mutex::Autolock lock(m_varLock); return m_usedLevel; } + // 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) { android::Mutex::Autolock lock(m_varLock); m_usedLevel = used; } + // assigns ownership of the texture to the tile if possible + bool acquire(BaseTile* owner); + + // private member accessor functions BaseTile* owner() { android::Mutex::Autolock lock(m_varLock); return m_owner; } - void setOwner(BaseTile* owner); BaseTile* painter() { return m_painter; } - void setPainter(BaseTile* painter); - bool busy() { android::Mutex::Autolock lock(m_varLock); return m_busy; } - void setBusy(bool value) { android::Mutex::Autolock lock(m_varLock); m_busy = value; } - uint32_t width() { return m_width; } - uint32_t height() { return m_height; } + SkCanvas* canvas() { return m_canvas; } + + // checks to see if the current readable texture equals the provided PaintingInfo bool consumerTextureUpToDate(PaintingInfo& info); + // checks to see if the current readable texture is similar to the provided PaintingInfo bool consumerTextureSimilar(PaintingInfo& info); - bool acquire(BaseTile* owner); - bool acquireForPainting(); private: SkBitmap m_bitmap; SkCanvas* m_canvas; - uint32_t m_width; - uint32_t m_height; int m_usedLevel; BaseTile* m_owner; BaseTile* m_painter; diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index 7471c70..b72cb6d 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -58,23 +58,22 @@ namespace WebCore { #ifdef DEBUG_COUNT -static int gBaseTextureCount = 0; +static int gBaseTileCount = 0; int BaseTile::count() { - return gBaseTextureCount; + return gBaseTileCount; } #endif -BaseTile::BaseTile(TiledPage* page, int x, int y, int quality) +BaseTile::BaseTile(TiledPage* page, int x, int y) : m_page(page) - , m_texture(0) , m_x(x) , m_y(y) - , m_quality(quality) + , m_texture(0) , m_scale(1) { #ifdef DEBUG_COUNT - gBaseTextureCount++; + gBaseTileCount++; #endif } @@ -83,7 +82,7 @@ BaseTile::~BaseTile() removeTexture(); setUsedLevel(-1); #ifdef DEBUG_COUNT - gBaseTextureCount--; + gBaseTileCount--; #endif } @@ -110,10 +109,6 @@ void BaseTile::setUsedLevel(int usedLevel) // Called from the main GL thread void BaseTile::draw(float transparency, SkRect& rect) { - m_varLock.lock(); - BackedDoubleBufferedTexture* texture = m_texture; - m_varLock.unlock(); - if (!m_texture) { XLOG("%x (%d, %d) trying to draw, but no m_texture!", this, x(), y()); return; @@ -121,19 +116,19 @@ void BaseTile::draw(float transparency, SkRect& rect) PaintingInfo info(m_x, m_y, m_page->glWebViewState()); - TextureInfo* textureInfo = texture->consumerLock(); + TextureInfo* textureInfo = m_texture->consumerLock(); if (!textureInfo) { XLOG("%x (%d, %d) trying to draw, but no textureInfo!", this, x(), y()); - texture->consumerRelease(); + m_texture->consumerRelease(); return; } - if (texture->consumerTextureSimilar(info)) { + if (m_texture->consumerTextureSimilar(info)) { TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, transparency); } - texture->consumerRelease(); + m_texture->consumerRelease(); } bool BaseTile::isBitmapReady() @@ -149,45 +144,38 @@ bool BaseTile::isBitmapReady() // Called from the texture generation thread bool BaseTile::paintBitmap() { + // the mutex ensures you are reading the most current value m_varLock.lock(); + const int x = m_x; + const int y = m_y; + const float scale = m_scale; + TiledPage* tiledPage = m_page; BackedDoubleBufferedTexture* texture = m_texture; m_varLock.unlock(); - bool available = false; - if (texture) - available = texture->acquireForPainting(); - - if (!texture || !available) + if (!texture) return false; + TextureInfo* textureInfo = texture->producerLock(); + // 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) { - texture->setBusy(false); + if (texture->owner() != this || texture->usedLevel() > 1) { + texture->producerRelease(); return false; } - PaintingInfo info(m_x, m_y, m_page->glWebViewState()); + PaintingInfo info(x, y, tiledPage->glWebViewState()); if (texture->consumerTextureUpToDate(info)) { - texture->setBusy(false); + texture->producerRelease(); return true; } - TextureInfo* textureInfo = texture->producerLock(); - - if (!textureInfo) { - texture->setBusy(false); - return false; - } - float tileWidth = textureInfo->m_width; float tileHeight = textureInfo->m_height; - float scale = m_scale / m_quality; - float invScale = 1 / scale; - + const float invScale = 1 / scale; float w = tileWidth * invScale; float h = tileHeight * invScale; @@ -196,9 +184,9 @@ bool BaseTile::paintBitmap() canvas->save(); canvas->scale(scale, scale); - canvas->translate(-m_x*w, -m_y*h); + canvas->translate(-x * w, -y * h); - bool didPaint = m_page->paintBaseLayerContent(canvas); + bool didPaint = tiledPage->paintBaseLayerContent(canvas); canvas->restore(); @@ -214,10 +202,7 @@ bool BaseTile::paintBitmap() canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint); #endif - texture->update(textureInfo, info); - texture->setPainter(this); - texture->setBusy(false); - texture->producerRelease(); + texture->producerUpdate(this, textureInfo, info); return didPaint; } diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h index e34c43d..31c306e 100644 --- a/WebCore/platform/graphics/android/BaseTile.h +++ b/WebCore/platform/graphics/android/BaseTile.h @@ -42,35 +42,58 @@ namespace WebCore { class BackedDoubleBufferedTexture; class TiledPage; +/** + * An individual tile that is used to construct part of a webpage's BaseLayer of + * content. Each tile is assigned to a TiledPage and is responsible for drawing + * and displaying their section of the page. The lifecycle of a tile is: + * + * 1. Each tile is created on the main GL thread and assigned to a specific + * location within a TiledPage. + * 2. When needed the tile is passed to the background thread where it paints + * the BaseLayer's most recent PictureSet to a bitmap which is then uploaded + * to the GPU. + * 3. After the bitmap is uploaded to the GPU the main GL thread then uses the + * tile's draw() function to display the tile to the screen. + * 4. Steps 2-3 are repeated as necessary. + * 5. The tile is destroyed when the user navigates to a new page. + * + */ class BaseTile { public: #ifdef DEBUG_COUNT static int count(); #endif - BaseTile(TiledPage* page, int x, int y, int quality = 1); + BaseTile(TiledPage* page, int x, int y); ~BaseTile(); void reserveTexture(); void removeTexture(); void setUsedLevel(int); - bool paintBitmap(); bool isBitmapReady(); + void draw(float transparency, SkRect& rect); + + // the only thread-safe function called by the background thread + bool paintBitmap(); + float scale() const { return m_scale; } void setScale(float scale) { m_scale = scale; } - void draw(float transparency, SkRect& rect); + TiledPage* page() { return m_page; } - int quality() const { return m_quality; } int x() const { return m_x; } int y() const { return m_y; } BackedDoubleBufferedTexture* texture() { return m_texture; } private: + // these variables are only set when the object is constructed TiledPage* m_page; - BackedDoubleBufferedTexture* m_texture; int m_x; int m_y; - int m_quality; + + // these variables can be updated throughout the lifetime of the object + BackedDoubleBufferedTexture* m_texture; float m_scale; + + // used to ensure the variables are consistent between threads android::Mutex m_varLock; }; diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp index 7cd69d6..ef261a0 100644 --- a/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp @@ -87,7 +87,7 @@ EGLContext DoubleBufferedTexture::producerAcquireContext() m_textureA.initSourceTexture(); m_textureB.initSourceTexture(); LOGV("Initialized Textures A/B (%d:%d)", m_textureA.getSourceTextureId(), - m_textureB.getSourceTextureId()); + m_textureB.getSourceTextureId()); m_textureA.unlock(); m_textureB.unlock(); @@ -110,11 +110,12 @@ TextureInfo* DoubleBufferedTexture::producerLock() void DoubleBufferedTexture::producerRelease() { - // get the front texture and cache the id - SharedTexture* sharedTex = getWriteableTexture(); - LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId()); + producerReleaseTexture(); +} - sharedTex->releaseSource(); +void DoubleBufferedTexture::producerReleaseAndSwap() +{ + SharedTexture* sharedTex = producerReleaseTexture(); // swap the front and back buffers m_varLock.lock(); @@ -123,6 +124,15 @@ void DoubleBufferedTexture::producerRelease() m_varLock.unlock(); } +SharedTexture* DoubleBufferedTexture::producerReleaseTexture() +{ + // get the front texture, unlock it, and return the id + SharedTexture* sharedTex = getWriteableTexture(); + LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId()); + sharedTex->releaseSource(); + return sharedTex; +} + TextureInfo* DoubleBufferedTexture::consumerLock() { m_varLock.lock(); diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/WebCore/platform/graphics/android/DoubleBufferedTexture.h index d6d06ab..de75479 100644 --- a/WebCore/platform/graphics/android/DoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.h @@ -38,8 +38,9 @@ public: virtual ~DoubleBufferedTexture() { } // provider thread functions - TextureInfo* producerLock(); - void producerRelease(); + virtual TextureInfo* producerLock(); + virtual void producerRelease(); + virtual void producerReleaseAndSwap(); EGLContext producerAcquireContext(); // consumer thread functions @@ -56,6 +57,7 @@ protected: private: SharedTexture* getWriteableTexture(); + SharedTexture* producerReleaseTexture(); EGLDisplay m_display; diff --git a/WebCore/platform/graphics/android/SharedTexture.h b/WebCore/platform/graphics/android/SharedTexture.h index 88aecfc..dc5dfd3 100644 --- a/WebCore/platform/graphics/android/SharedTexture.h +++ b/WebCore/platform/graphics/android/SharedTexture.h @@ -51,8 +51,8 @@ public: bool operator==(const TextureInfo& otherTexture); GLuint m_textureId; - uint32_t m_width; - uint32_t m_height; + int32_t m_width; + int32_t m_height; GLenum m_internalFormat; }; diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index a600f39..feaccb8 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -133,8 +133,7 @@ void TilesManager::paintTexturesDefault() canvas->drawARGB(255, 255, 255, 255); #endif // DEBUG PaintingInfo info; - texture->update(textureInfo, info); - texture->producerRelease(); + texture->producerUpdate(0, textureInfo, info); } } } |