SkBitmap ImageFrameGenerator::tryToResumeDecode(size_t index, const SkISize& scaledSize)
{
    TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    SkBitmap fullSizeImage;
    bool complete = decode(index, &decoder, &fullSizeImage);

    if (!decoder)
        return SkBitmap();

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (fullSizeImage.isNull()) {
        // If decoding has failed, we can save work in the future by
        // ignoring further requests to decode the image.
        m_decodeFailed = decoder->failed();
        if (resumeDecoding)
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
        return SkBitmap();
    }

    bool removeDecoder = false;
    if (complete) {
        // Free as much memory as possible.  For single-frame images, we can
        // just delete the decoder entirely.  For multi-frame images, we keep
        // the decoder around in order to preserve decoded information such as
        // the required previous frame indexes, but if we've reached the last
        // frame we can at least delete all the cached frames.  (If we were to
        // do this before reaching the last frame, any subsequent requested
        // frames which relied on the current frame would trigger extra
        // re-decoding of all frames in the dependency chain.)
        if (!m_isMultiFrame)
            removeDecoder = true;
        else if (index == m_frameCount - 1)
            decoder->clearCacheExceptFrame(kNotFound);
    }

    if (resumeDecoding) {
        if (removeDecoder)
            ImageDecodingStore::instance().removeDecoder(this, decoder);
        else
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
    } else if (!removeDecoder) {
        ImageDecodingStore::instance().insertDecoder(this, decoderContainer.release());
    }
    return fullSizeImage;
}
Ejemplo n.º 2
0
const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const SkISize& scaledSize, size_t index)
{
    TRACE_EVENT1("webkit", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance()->lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    OwnPtr<ScaledImageFragment> fullSizeImage = decode(index, &decoder);

    if (!decoder)
        return 0;

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (!fullSizeImage) {
        // If decode has failed and resulted an empty image we can save work
        // in the future by returning early.
        m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();

        if (resumeDecoding)
            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
        return 0;
    }

    const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(this, fullSizeImage.release());

    // If the image generated is complete then there is no need to keep
    // the decoder. The exception is multi-frame decoder which can generate
    // multiple complete frames.
    const bool removeDecoder = cachedImage->isComplete() && !m_isMultiFrame;

    if (resumeDecoding) {
        if (removeDecoder)
            ImageDecodingStore::instance()->removeDecoder(this, decoder);
        else
            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
    } else if (!removeDecoder) {
        ImageDecodingStore::instance()->insertDecoder(this, decoderContainer.release(), DiscardablePixelRef::isDiscardable(cachedImage->bitmap().pixelRef()));
    }

    if (m_fullSize == scaledSize)
        return cachedImage;
    return tryToScale(cachedImage, scaledSize, index);
}
Ejemplo n.º 3
0
SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index)
{
    TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance()->lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    SkBitmap fullSizeImage;
    bool complete = decode(index, &decoder, &fullSizeImage);

    if (!decoder)
        return SkBitmap();

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (fullSizeImage.isNull()) {
        // If decode has failed and resulted an empty image we can save work
        // in the future by returning early.
        m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();

        if (resumeDecoding)
            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
        return SkBitmap();
    }

    // If the image generated is complete then there is no need to keep
    // the decoder. The exception is multi-frame decoder which can generate
    // multiple complete frames.
    const bool removeDecoder = complete && !m_isMultiFrame;

    if (resumeDecoding) {
        if (removeDecoder)
            ImageDecodingStore::instance()->removeDecoder(this, decoder);
        else
            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
    } else if (!removeDecoder) {
        ImageDecodingStore::instance()->insertDecoder(this, decoderContainer.release());
    }
    return fullSizeImage;
}
Ejemplo n.º 4
0
SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index)
{
    TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    SkBitmap fullSizeImage;
    bool complete = decode(index, &decoder, &fullSizeImage);

    if (!decoder)
        return SkBitmap();
    if (index >= m_frameComplete.size())
        m_frameComplete.resize(index + 1);
    m_frameComplete[index] = complete;

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (fullSizeImage.isNull()) {
        // If decode has failed and resulted an empty image we can save work
        // in the future by returning early.
        m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();

        if (resumeDecoding)
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
        return SkBitmap();
    }

    // If the image generated is complete then there is no need to keep
    // the decoder. For multi-frame images, if all frames in the image are
    // decoded, we remove the decoder.
    bool removeDecoder;

    if (m_isMultiFrame) {
        size_t decodedFrameCount = 0;
        for (Vector<bool>::iterator it = m_frameComplete.begin(); it != m_frameComplete.end(); ++it) {
            if (*it)
                decodedFrameCount++;
        }
        removeDecoder = m_frameCount && (decodedFrameCount == m_frameCount);
    } else {
        removeDecoder = complete;
    }

    if (resumeDecoding) {
        if (removeDecoder) {
            ImageDecodingStore::instance().removeDecoder(this, decoder);
            m_frameComplete.clear();
        } else {
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
        }
    } else if (!removeDecoder) {
        ImageDecodingStore::instance().insertDecoder(this, decoderContainer.release());
    }
    return fullSizeImage;
}