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; }
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); }
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; }
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; }