Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      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  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "platform/graphics/DeferredImageDecoder.h"
     28 
     29 #include "platform/graphics/DecodingImageGenerator.h"
     30 #include "platform/graphics/ImageDecodingStore.h"
     31 #include "platform/graphics/LazyDecodingPixelRef.h"
     32 #include "third_party/skia/include/core/SkImageInfo.h"
     33 #include "wtf/PassOwnPtr.h"
     34 
     35 namespace WebCore {
     36 
     37 namespace {
     38 
     39 // URI label for SkDiscardablePixelRef.
     40 const char labelDiscardable[] = "discardable";
     41 
     42 } // namespace
     43 
     44 bool DeferredImageDecoder::s_enabled = false;
     45 
     46 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
     47     : m_allDataReceived(false)
     48     , m_lastDataSize(0)
     49     , m_dataChanged(false)
     50     , m_actualDecoder(actualDecoder)
     51     , m_orientation(DefaultImageOrientation)
     52     , m_repetitionCount(cAnimationNone)
     53     , m_hasColorProfile(false)
     54 {
     55 }
     56 
     57 DeferredImageDecoder::~DeferredImageDecoder()
     58 {
     59 }
     60 
     61 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption)
     62 {
     63     OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
     64     return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr;
     65 }
     66 
     67 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
     68 {
     69     return adoptPtr(new DeferredImageDecoder(decoder));
     70 }
     71 
     72 bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
     73 {
     74     return bitmap.pixelRef()
     75         && bitmap.pixelRef()->getURI()
     76         && !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable));
     77 }
     78 
     79 void DeferredImageDecoder::setEnabled(bool enabled)
     80 {
     81     s_enabled = enabled;
     82     if (enabled)
     83         ImageDecodingStore::setImageCachingEnabled(false);
     84 }
     85 
     86 bool DeferredImageDecoder::enabled()
     87 {
     88     return s_enabled;
     89 }
     90 
     91 String DeferredImageDecoder::filenameExtension() const
     92 {
     93     return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
     94 }
     95 
     96 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
     97 {
     98     prepareLazyDecodedFrames();
     99     if (index < m_lazyDecodedFrames.size()) {
    100         // ImageFrameGenerator has the latest known alpha state. There will
    101         // be a performance boost if this frame is opaque.
    102         m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index));
    103         return m_lazyDecodedFrames[index].get();
    104     }
    105     if (m_actualDecoder)
    106         return m_actualDecoder->frameBufferAtIndex(index);
    107     return 0;
    108 }
    109 
    110 void DeferredImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
    111 {
    112     if (m_actualDecoder) {
    113         const bool firstData = !m_data;
    114         const bool moreData = data.size() > m_lastDataSize;
    115         m_dataChanged = firstData || moreData;
    116         m_data = RefPtr<SharedBuffer>(data);
    117         m_lastDataSize = data.size();
    118         m_allDataReceived = allDataReceived;
    119         m_actualDecoder->setData(&data, allDataReceived);
    120         prepareLazyDecodedFrames();
    121     }
    122 
    123     if (m_frameGenerator)
    124         m_frameGenerator->setData(&data, allDataReceived);
    125 }
    126 
    127 bool DeferredImageDecoder::isSizeAvailable()
    128 {
    129     // m_actualDecoder is 0 only if image decoding is deferred and that
    130     // means image header decoded successfully and size is available.
    131     return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
    132 }
    133 
    134 bool DeferredImageDecoder::hasColorProfile() const
    135 {
    136     return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile;
    137 }
    138 
    139 IntSize DeferredImageDecoder::size() const
    140 {
    141     return m_actualDecoder ? m_actualDecoder->size() : m_size;
    142 }
    143 
    144 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
    145 {
    146     // FIXME: LocalFrame size is assumed to be uniform. This might not be true for
    147     // future supported codecs.
    148     return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
    149 }
    150 
    151 size_t DeferredImageDecoder::frameCount()
    152 {
    153     return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
    154 }
    155 
    156 int DeferredImageDecoder::repetitionCount() const
    157 {
    158     return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
    159 }
    160 
    161 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
    162 {
    163     // If image decoding is deferred then frame buffer cache is managed by
    164     // the compositor and this call is ignored.
    165     return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptFrame) : 0;
    166 }
    167 
    168 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
    169 {
    170     if (m_actualDecoder)
    171         return m_actualDecoder->frameHasAlphaAtIndex(index);
    172     if (!m_frameGenerator->isMultiFrame())
    173         return m_frameGenerator->hasAlpha(index);
    174     return true;
    175 }
    176 
    177 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
    178 {
    179     if (m_actualDecoder)
    180         return m_actualDecoder->frameIsCompleteAtIndex(index);
    181     if (index < m_lazyDecodedFrames.size())
    182         return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete;
    183     return false;
    184 }
    185 
    186 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
    187 {
    188     if (m_actualDecoder)
    189         return m_actualDecoder->frameDurationAtIndex(index);
    190     if (index < m_lazyDecodedFrames.size())
    191         return m_lazyDecodedFrames[index]->duration();
    192     return 0;
    193 }
    194 
    195 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
    196 {
    197     // If frame decoding is deferred then it is not managed by MemoryCache
    198     // so return 0 here.
    199     return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
    200 }
    201 
    202 ImageOrientation DeferredImageDecoder::orientation() const
    203 {
    204     return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
    205 }
    206 
    207 void DeferredImageDecoder::activateLazyDecoding()
    208 {
    209     if (m_frameGenerator)
    210         return;
    211     m_size = m_actualDecoder->size();
    212     m_orientation = m_actualDecoder->orientation();
    213     m_filenameExtension = m_actualDecoder->filenameExtension();
    214     m_hasColorProfile = m_actualDecoder->hasColorProfile();
    215     const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
    216     m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame);
    217 }
    218 
    219 void DeferredImageDecoder::prepareLazyDecodedFrames()
    220 {
    221     if (!s_enabled
    222         || !m_actualDecoder
    223         || !m_actualDecoder->isSizeAvailable()
    224         || m_actualDecoder->filenameExtension() == "ico")
    225         return;
    226 
    227     activateLazyDecoding();
    228 
    229     const size_t previousSize = m_lazyDecodedFrames.size();
    230     m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
    231 
    232     // We have encountered a broken image file. Simply bail.
    233     if (m_lazyDecodedFrames.size() < previousSize)
    234         return;
    235 
    236     for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
    237         OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
    238         frame->setSkBitmap(createBitmap(i));
    239         frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
    240         frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
    241         m_lazyDecodedFrames[i] = frame.release();
    242     }
    243 
    244     // The last lazy decoded frame created from previous call might be
    245     // incomplete so update its state.
    246     if (previousSize) {
    247         const size_t lastFrame = previousSize - 1;
    248         m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
    249 
    250         // If data has changed then create a new bitmap. This forces
    251         // Skia to decode again.
    252         if (m_dataChanged) {
    253             m_dataChanged = false;
    254             m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
    255         }
    256     }
    257 
    258     if (m_allDataReceived) {
    259         m_repetitionCount = m_actualDecoder->repetitionCount();
    260         m_actualDecoder.clear();
    261         m_data = nullptr;
    262     }
    263 }
    264 
    265 // Creates a SkBitmap that is backed by SkDiscardablePixelRef.
    266 SkBitmap DeferredImageDecoder::createBitmap(size_t index)
    267 {
    268     IntSize decodedSize = m_actualDecoder->decodedSize();
    269     ASSERT(decodedSize.width() > 0);
    270     ASSERT(decodedSize.height() > 0);
    271 
    272     SkImageInfo info;
    273     info.fWidth = decodedSize.width();
    274     info.fHeight = decodedSize.height();
    275 #if SK_B32_SHIFT // Little-endian RGBA pixels. (Android)
    276     info.fColorType = kRGBA_8888_SkColorType;
    277 #else
    278     info.fColorType = kBGRA_8888_SkColorType;
    279 #endif
    280     info.fAlphaType = kPremul_SkAlphaType;
    281 
    282     SkBitmap bitmap;
    283     DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index);
    284     bool installed = SkInstallDiscardablePixelRef(generator, &bitmap);
    285     ASSERT_UNUSED(installed, installed);
    286     bitmap.pixelRef()->setURI(labelDiscardable);
    287     generator->setGenerationId(bitmap.getGenerationID());
    288     return bitmap;
    289 }
    290 
    291 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
    292 {
    293     // TODO: Implement.
    294     return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
    295 }
    296 
    297 } // namespace WebCore
    298