Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2011, 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 "ImageTexture.h"
     28 
     29 #include "ImagesManager.h"
     30 #include "LayerAndroid.h"
     31 #include "SkDevice.h"
     32 #include "SkPicture.h"
     33 #include "TilesManager.h"
     34 #include "TiledTexture.h"
     35 
     36 #include <cutils/log.h>
     37 #include <wtf/CurrentTime.h>
     38 #include <wtf/text/CString.h>
     39 
     40 #undef XLOGC
     41 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__)
     42 
     43 #ifdef DEBUG
     44 
     45 #undef XLOG
     46 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__)
     47 
     48 #else
     49 
     50 #undef XLOG
     51 #define XLOG(...)
     52 
     53 #endif // DEBUG
     54 
     55 namespace WebCore {
     56 
     57 // CRC computation adapted from Tools/DumpRenderTree/CyclicRedundancyCheck.cpp
     58 static void makeCrcTable(unsigned crcTable[256])
     59 {
     60     for (unsigned i = 0; i < 256; i++) {
     61         unsigned c = i;
     62         for (int k = 0; k < 8; k++) {
     63             if (c & 1)
     64                 c = -306674912 ^ ((c >> 1) & 0x7fffffff);
     65             else
     66                 c = c >> 1;
     67         }
     68         crcTable[i] = c;
     69     }
     70 }
     71 
     72 unsigned computeCrc(uint8_t* buffer, size_t size)
     73 {
     74     static unsigned crcTable[256];
     75     static bool crcTableComputed = false;
     76     if (!crcTableComputed) {
     77         makeCrcTable(crcTable);
     78         crcTableComputed = true;
     79     }
     80 
     81     unsigned crc = 0xffffffffL;
     82     for (size_t i = 0; i < size; ++i)
     83         crc = crcTable[(crc ^ buffer[i]) & 0xff] ^ ((crc >> 8) & 0x00ffffffL);
     84     return crc ^ 0xffffffffL;
     85 }
     86 
     87 ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc)
     88     : m_image(bmp)
     89     , m_texture(0)
     90     , m_layer(0)
     91     , m_picture(0)
     92     , m_crc(crc)
     93 {
     94 #ifdef DEBUG_COUNT
     95     ClassTracker::instance()->increment("ImageTexture");
     96 #endif
     97     if (!m_image)
     98         return;
     99 
    100     // NOTE: This constructor is called on the webcore thread
    101 
    102     // Create a picture containing the image (needed for TiledTexture)
    103     m_picture = new SkPicture();
    104     SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height());
    105     pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0));
    106     pcanvas->drawBitmap(*m_image, 0, 0);
    107     m_picture->endRecording();
    108 }
    109 
    110 ImageTexture::~ImageTexture()
    111 {
    112 #ifdef DEBUG_COUNT
    113     ClassTracker::instance()->decrement("ImageTexture");
    114 #endif
    115     delete m_image;
    116     delete m_texture;
    117     SkSafeUnref(m_picture);
    118 }
    119 
    120 SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap)
    121 {
    122     SkBitmap* img = new SkBitmap();
    123     int w = bitmap->width();
    124     int h = bitmap->height();
    125 
    126     // Create a copy of the image
    127     img->setConfig(SkBitmap::kARGB_8888_Config, w, h);
    128     img->allocPixels();
    129     SkDevice* device = new SkDevice(NULL, *img, false);
    130     SkCanvas canvas;
    131     canvas.setDevice(device);
    132     device->unref();
    133     SkRect dest;
    134     dest.set(0, 0, w, h);
    135     img->setIsOpaque(false);
    136     img->eraseARGB(0, 0, 0, 0);
    137     canvas.drawBitmapRect(*bitmap, 0, dest);
    138 
    139     return img;
    140 }
    141 
    142 unsigned ImageTexture::computeCRC(const SkBitmap* bitmap)
    143 {
    144     if (!bitmap)
    145         return 0;
    146     bitmap->lockPixels();
    147     uint8_t* img = static_cast<uint8_t*>(bitmap->getPixels());
    148     unsigned crc = computeCrc(img, bitmap->getSize());
    149     bitmap->unlockPixels();
    150     return crc;
    151 }
    152 
    153 bool ImageTexture::equalsCRC(unsigned crc)
    154 {
    155     return m_crc == crc;
    156 }
    157 
    158 int ImageTexture::nbTextures()
    159 {
    160     if (!hasContentToShow())
    161         return 0;
    162     if (!m_texture)
    163         return 0;
    164 
    165     // TODO: take in account the visible clip (need to maintain
    166     // a list of the clients layer, etc.)
    167     IntRect visibleArea(0, 0, m_image->width(), m_image->height());
    168     int nbTextures = m_texture->nbTextures(visibleArea, 1.0);
    169     XLOG("ImageTexture %p, %d x %d needs %d textures",
    170           this, m_image->width(), m_image->height(),
    171           nbTextures);
    172     return nbTextures;
    173 }
    174 
    175 bool ImageTexture::hasContentToShow()
    176 {
    177     // Don't display 1x1 image -- no need to allocate a full texture for this
    178     if (!m_image)
    179         return false;
    180     if (m_image->width() == 1 && m_image->height() == 1)
    181         return false;
    182     return true;
    183 }
    184 
    185 bool ImageTexture::prepareGL(GLWebViewState* state)
    186 {
    187     if (!hasContentToShow())
    188         return false;
    189 
    190     if (!m_texture && m_picture) {
    191         m_texture = new TiledTexture(this);
    192         SkRegion region;
    193         region.setRect(0, 0, m_image->width(), m_image->height());
    194         m_texture->update(region, m_picture);
    195     }
    196 
    197     if (!m_texture)
    198         return false;
    199 
    200     IntRect visibleArea(0, 0, m_image->width(), m_image->height());
    201     m_texture->prepare(state, 1.0, true, true, visibleArea);
    202     if (m_texture->ready()) {
    203         m_texture->swapTiles();
    204         return false;
    205     }
    206     return true;
    207 }
    208 
    209 const TransformationMatrix* ImageTexture::transform()
    210 {
    211     if (!m_layer)
    212         return 0;
    213 
    214     FloatPoint p(0, 0);
    215     p = m_layer->drawTransform()->mapPoint(p);
    216     IntRect layerArea = m_layer->unclippedArea();
    217     float scaleW = static_cast<float>(layerArea.width()) / static_cast<float>(m_image->width());
    218     float scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(m_image->height());
    219     TransformationMatrix d = *(m_layer->drawTransform());
    220     TransformationMatrix m;
    221     m.scaleNonUniform(scaleW, scaleH);
    222     m_layerMatrix = d.multiply(m);
    223     return &m_layerMatrix;
    224 }
    225 
    226 float ImageTexture::opacity()
    227 {
    228     if (!m_layer)
    229         return 1.0;
    230     return m_layer->drawOpacity();
    231 }
    232 
    233 void ImageTexture::drawGL(LayerAndroid* layer)
    234 {
    235     if (!layer)
    236         return;
    237     if (!hasContentToShow())
    238         return;
    239 
    240     // TiledTexture::draw() will call us back to know the
    241     // transform and opacity, so we need to set m_layer
    242     m_layer = layer;
    243     if (m_texture)
    244         m_texture->draw();
    245     m_layer = 0;
    246 }
    247 
    248 void ImageTexture::drawCanvas(SkCanvas* canvas, SkRect& rect)
    249 {
    250     if (canvas && m_image)
    251         canvas->drawBitmapRect(*m_image, 0, rect);
    252 }
    253 
    254 } // namespace WebCore
    255