Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2010, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "BaseTileTexture.h"
     28 
     29 #include "BaseTile.h"
     30 #include "ClassTracker.h"
     31 #include "DeleteTextureOperation.h"
     32 #include "GLUtils.h"
     33 #include "TilesManager.h"
     34 
     35 #include <cutils/log.h>
     36 #include <wtf/text/CString.h>
     37 
     38 #undef XLOGC
     39 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
     40 
     41 #ifdef DEBUG
     42 
     43 #undef XLOG
     44 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
     45 
     46 #else
     47 
     48 #undef XLOG
     49 #define XLOG(...)
     50 
     51 #endif // DEBUG
     52 
     53 namespace WebCore {
     54 
     55 BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h)
     56     : DoubleBufferedTexture(eglGetCurrentContext(),
     57                             TilesManager::instance()->getSharedTextureMode())
     58     , m_owner(0)
     59     , m_busy(false)
     60 {
     61     m_size.set(w, h);
     62     m_ownTextureId = 0;
     63 
     64     // Make sure they are created on the UI thread.
     65     TilesManager::instance()->transferQueue()->initSharedSurfaceTextures(w, h);
     66 
     67 #ifdef DEBUG_COUNT
     68     ClassTracker::instance()->increment("BaseTileTexture");
     69 #endif
     70 }
     71 
     72 BaseTileTexture::~BaseTileTexture()
     73 {
     74     if (m_sharedTextureMode == EglImageMode) {
     75         SharedTexture* textures[3] = { m_textureA, m_textureB, 0 };
     76         destroyTextures(textures);
     77     }
     78 #ifdef DEBUG_COUNT
     79     ClassTracker::instance()->decrement("BaseTileTexture");
     80 #endif
     81 }
     82 
     83 void BaseTileTexture::requireGLTexture()
     84 {
     85     if (!m_ownTextureId)
     86         m_ownTextureId = GLUtils::createBaseTileGLTexture(m_size.width(), m_size.height());
     87 }
     88 
     89 void BaseTileTexture::discardGLTexture()
     90 {
     91     if (m_ownTextureId)
     92         GLUtils::deleteTexture(&m_ownTextureId);
     93 
     94     if (m_owner) {
     95         // clear both Tile->Texture and Texture->Tile links
     96         m_owner->removeTexture(this);
     97         release(m_owner);
     98     }
     99 }
    100 
    101 void BaseTileTexture::destroyTextures(SharedTexture** textures)
    102 {
    103     int x = 0;
    104     while (textures[x]) {
    105         // We need to delete the source texture and EGLImage in the texture
    106         // generation thread. In theory we should be able to delete the EGLImage
    107         // from either thread, but it currently throws an error if not deleted
    108         // in the same EGLContext from which it was created.
    109         textures[x]->lock();
    110         DeleteTextureOperation* operation = new DeleteTextureOperation(
    111             textures[x]->getSourceTextureId(), textures[x]->getEGLImage());
    112         textures[x]->unlock();
    113         TilesManager::instance()->scheduleOperation(operation);
    114         x++;
    115     }
    116 }
    117 
    118 TextureInfo* BaseTileTexture::producerLock()
    119 {
    120     m_busyLock.lock();
    121     m_busy = true;
    122     m_busyLock.unlock();
    123     return DoubleBufferedTexture::producerLock();
    124 }
    125 
    126 void BaseTileTexture::producerRelease()
    127 {
    128     DoubleBufferedTexture::producerRelease();
    129     setNotBusy();
    130 }
    131 
    132 void BaseTileTexture::producerReleaseAndSwap()
    133 {
    134     DoubleBufferedTexture::producerReleaseAndSwap();
    135     setNotBusy();
    136 }
    137 
    138 void BaseTileTexture::setNotBusy()
    139 {
    140     android::Mutex::Autolock lock(m_busyLock);
    141     m_busy = false;
    142     m_busyCond.signal();
    143 }
    144 
    145 bool BaseTileTexture::busy()
    146 {
    147     android::Mutex::Autolock lock(m_busyLock);
    148     return m_busy;
    149 }
    150 
    151 void BaseTileTexture::producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap)
    152 {
    153     // no need to upload a texture since the bitmap is empty
    154     if (!bitmap.width() && !bitmap.height()) {
    155         producerRelease();
    156         return;
    157     }
    158 
    159     // After the tiled layer checked in, this is not called anyway.
    160     // TODO: cleanup the old code path for layer painting
    161     // GLUtils::paintTextureWithBitmap(info, m_size, bitmap, 0, 0);
    162 
    163     producerReleaseAndSwap();
    164 }
    165 
    166 bool BaseTileTexture::acquire(TextureOwner* owner, bool force)
    167 {
    168     if (m_owner == owner)
    169         return true;
    170 
    171     return setOwner(owner, force);
    172 }
    173 
    174 bool BaseTileTexture::setOwner(TextureOwner* owner, bool force)
    175 {
    176     // if the writable texture is busy (i.e. currently being written to) then we
    177     // can't change the owner out from underneath that texture
    178     m_busyLock.lock();
    179     while (m_busy && force)
    180         m_busyCond.wait(m_busyLock);
    181     bool busy = m_busy;
    182     m_busyLock.unlock();
    183 
    184     if (!busy) {
    185         // if we are not busy we can try to remove the texture from the layer;
    186         // LayerAndroid::removeTexture() is protected by the same lock as
    187         // LayerAndroid::paintBitmapGL(), so either we execute removeTexture()
    188         // first and paintBitmapGL() will bail out, or we execute it after,
    189         // and paintBitmapGL() will mark the texture as busy before
    190         // relinquishing the lock. LayerAndroid::removeTexture() will call
    191         // BaseTileTexture::release(), which will then do nothing
    192         // if the texture is busy and we then don't return true.
    193         bool proceed = true;
    194         if (m_owner && m_owner != owner)
    195             proceed = m_owner->removeTexture(this);
    196 
    197         if (proceed) {
    198             m_owner = owner;
    199             return true;
    200         }
    201     }
    202     return false;
    203 }
    204 
    205 bool BaseTileTexture::release(TextureOwner* owner)
    206 {
    207     android::Mutex::Autolock lock(m_busyLock);
    208     XLOG("texture %p releasing tile %p, m_owner %p, m_busy %d", this, owner, m_owner, m_busy);
    209     if (m_owner != owner)
    210         return false;
    211 
    212     m_owner = 0;
    213     return true;
    214 }
    215 
    216 void BaseTileTexture::setTile(TextureInfo* info, int x, int y,
    217                                           float scale, TilePainter* painter,
    218                                           unsigned int pictureCount)
    219 {
    220     TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture());
    221     if (!textureInfo) {
    222         textureInfo = new TextureTileInfo();
    223     }
    224     textureInfo->m_x = x;
    225     textureInfo->m_y = y;
    226     textureInfo->m_scale = scale;
    227     textureInfo->m_painter = painter;
    228     textureInfo->m_picture = pictureCount;
    229     m_texturesInfo.set(getWriteableTexture(), textureInfo);
    230 }
    231 
    232 float BaseTileTexture::scale()
    233 {
    234     TextureTileInfo* textureInfo = &m_ownTextureTileInfo;
    235     return textureInfo->m_scale;
    236 }
    237 
    238 // This function + TilesManager::addItemInTransferQueue() is replacing the
    239 // setTile().
    240 void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info)
    241 {
    242     m_ownTextureTileInfo.m_x = info->m_x;
    243     m_ownTextureTileInfo.m_y = info->m_y;
    244     m_ownTextureTileInfo.m_scale = info->m_scale;
    245     m_ownTextureTileInfo.m_painter = info->m_painter;
    246     m_ownTextureTileInfo.m_picture = info->m_picture;
    247     m_ownTextureTileInfo.m_inverted = TilesManager::instance()->invertedScreen();
    248     if (m_owner) {
    249         BaseTile* owner = static_cast<BaseTile*>(m_owner);
    250         owner->backTextureTransfer();
    251     }
    252 
    253 }
    254 
    255 bool BaseTileTexture::readyFor(BaseTile* baseTile)
    256 {
    257     const TextureTileInfo* info = &m_ownTextureTileInfo;
    258     if (info &&
    259         (info->m_x == baseTile->x()) &&
    260         (info->m_y == baseTile->y()) &&
    261         (info->m_scale == baseTile->scale()) &&
    262         (info->m_painter == baseTile->painter()) &&
    263         (info->m_inverted == TilesManager::instance()->invertedScreen()))
    264         return true;
    265 
    266     XLOG("texture %p readyFor return false for tile x, y (%d %d) texId %d ,"
    267          " BaseTileTexture %p, BaseTile is %p, SCALE %f, painter %p, inv %d",
    268          this, baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile,
    269          baseTile->scale(), baseTile->painter(), TilesManager::instance()->invertedScreen());
    270     return false;
    271 }
    272 
    273 } // namespace WebCore
    274