예제 #1
0
const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& scaledSize)
{
    // Prevents concurrent decode or scale operations on the same image data.
    // Multiple LazyDecodingPixelRefs can call this method at the same time.
    MutexLocker lock(m_decodeMutex);
    if (m_decodeFailedAndEmpty)
        return 0;

    const ScaledImageFragment* cachedImage = 0;

    cachedImage = tryToLockCompleteCache(scaledSize);
    if (cachedImage)
        return cachedImage;

    cachedImage = tryToScale(0, scaledSize);
    if (cachedImage)
        return cachedImage;

    cachedImage = tryToResumeDecodeAndScale(scaledSize);
    if (cachedImage)
        return cachedImage;

    cachedImage = tryToDecodeAndScale(scaledSize);
    if (cachedImage)
        return cachedImage;
    return 0;
}
const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& scaledSize, size_t index)
{
    // Prevents concurrent decode or scale operations on the same image data.
    // Multiple LazyDecodingPixelRefs can call this method at the same time.
    MutexLocker lock(m_decodeMutex);
    if (m_decodeFailedAndEmpty)
        return 0;

    const ScaledImageFragment* cachedImage = 0;

    cachedImage = tryToLockCompleteCache(scaledSize, index);
    if (cachedImage)
        return cachedImage;

    TRACE_EVENT2("webkit", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", static_cast<int>(m_decodeCount));

    cachedImage = tryToScale(0, scaledSize, index);
    if (cachedImage)
        return cachedImage;

    cachedImage = tryToResumeDecodeAndScale(scaledSize, index);
    if (cachedImage)
        return cachedImage;
    return 0;
}
예제 #3
0
const ScaledImageFragment* ImageFrameGenerator::tryToDecodeAndScale(const SkISize& scaledSize)
{
    TRACE_EVENT0("webkit", "ImageFrameGenerator::tryToDecodeAndScale");

    ImageDecoder* decoder = 0;
    OwnPtr<ScaledImageFragment> fullSizeImage = decode(&decoder);

    if (!decoder)
        return 0;

    OwnPtr<ImageDecoder> decoderContainer = adoptPtr(decoder);

    if (!fullSizeImage) {
        // If decode has failed and resulted an empty image we need to make
        // sure we don't do wasted work in the future.
        m_decodeFailedAndEmpty = decoderContainer->failed();
        return 0;
    }

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

    if (m_fullSize == scaledSize)
        return cachedFullSizeImage;
    return tryToScale(cachedFullSizeImage, scaledSize);
}
예제 #4
0
const ScaledImageFragment* ImageFrameGenerator::tryToDecodeAndScale(const SkISize& scaledSize)
{
    RefPtr<SharedBuffer> data;
    bool allDataReceived = false;
    {
        MutexLocker lock(m_dataMutex);

        // FIXME: We should do a shallow copy instead. Now we're restricted by the API of SharedBuffer.
        data = m_data->copy();
        allDataReceived = m_allDataReceived;
    }

    OwnPtr<ImageDecoder> decoder(adoptPtr(ImageDecoder::create(*data.get(), ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileApplied)));
    if (!decoder && m_imageDecoderFactory)
        decoder = m_imageDecoderFactory->create();
    if (!decoder)
        return 0;

    decoder->setData(data.get(), allDataReceived);
    ImageFrame* frame = decoder->frameBufferAtIndex(0);
    if (!frame || frame->status() == ImageFrame::FrameEmpty)
        return 0;

    bool isComplete = frame->status() == ImageFrame::FrameComplete;
    SkBitmap fullSizeBitmap = frame->getSkBitmap();
    ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.height() == m_fullSize.height());

    const ScaledImageFragment* fullSizeImage = ImageDecodingStore::instance()->insertAndLockCache(
        this, ScaledImageFragment::create(m_fullSize, fullSizeBitmap, isComplete));

    if (m_fullSize == scaledSize)
        return fullSizeImage;
    return tryToScale(fullSizeImage, scaledSize);
}
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);
}
예제 #6
0
const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const SkISize& scaledSize)
{
    const ScaledImageFragment* cachedImage = 0;
    ImageDecoder* cachedDecoder = 0;
    if (!ImageDecodingStore::instance()->lockCache(this, m_fullSize, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &cachedDecoder))
        return 0;
    ASSERT(cachedDecoder);

    if (m_data.hasNewData()) {
        // Only do decoding if there is new data.
        OwnPtr<ScaledImageFragment> fullSizeImage = decode(&cachedDecoder);
        cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(this, cachedImage, fullSizeImage.release());
    }

    if (m_fullSize == scaledSize)
        return cachedImage;
    return tryToScale(cachedImage, scaledSize);
}