DrawableSurface RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize, uint32_t aFlags) { MOZ_ASSERT(NS_IsMainThread()); if (mError) { return DrawableSurface(); } if (!mHasSize) { mWantFullDecode = true; return DrawableSurface(); } // Decide whether to sync decode images we can decode quickly. Here we are // explicitly trading off flashing for responsiveness in the case that we're // redecoding an image (see bug 845147). bool shouldSyncDecodeIfFast = !mHasBeenDecoded && (aFlags & FLAG_SYNC_DECODE_IF_FAST); uint32_t flags = shouldSyncDecodeIfFast ? aFlags : aFlags & ~FLAG_SYNC_DECODE_IF_FAST; // Perform a frame lookup, which will implicitly start decoding if needed. return LookupFrame(aSize, flags, mAnimationState ? PlaybackType::eAnimated : PlaybackType::eStatic); }
LookupResult FrameAnimator::GetCompositedFrame(AnimationState& aState) { // If we have a composited version of this frame, return that. if (mLastCompositedFrameIndex >= 0 && (uint32_t(mLastCompositedFrameIndex) == aState.mCurrentAnimationFrameIndex)) { return LookupResult(DrawableSurface(mCompositingFrame->DrawableRef()), MatchType::EXACT); } // Otherwise return the raw frame. DoBlend is required to ensure that we only // hit this case if the frame is not paletted and doesn't require compositing. LookupResult result = SurfaceCache::Lookup(ImageKey(mImage), RasterSurfaceKey(mSize, DefaultSurfaceFlags(), PlaybackType::eAnimated)); if (!result) { return result; } // Seek to the appropriate frame. If seeking fails, it means that we couldn't // get the frame we're looking for; treat this as if the lookup failed. if (NS_FAILED(result.Surface().Seek(aState.mCurrentAnimationFrameIndex))) { return LookupResult(MatchType::NOT_FOUND); } MOZ_ASSERT(!result.Surface()->GetIsPaletted(), "About to return a paletted frame"); return result; }
DrawableSurface RasterImage::LookupFrame(const IntSize& aSize, uint32_t aFlags, PlaybackType aPlaybackType) { MOZ_ASSERT(NS_IsMainThread()); // If we're opaque, we don't need to care about premultiplied alpha, because // that can only matter for frames with transparency. if (IsOpaque()) { aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; } IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags) ? aSize : mSize; if (requestedSize.IsEmpty()) { return DrawableSurface(); // Can't decode to a surface of zero size. } LookupResult result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType); if (!result && !mHasSize) { // We can't request a decode without knowing our intrinsic size. Give up. return DrawableSurface(); } if (result.Type() == MatchType::NOT_FOUND || result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND || ((aFlags & FLAG_SYNC_DECODE) && !result)) { // We don't have a copy of this frame, and there's no decoder working on // one. (Or we're sync decoding and the existing decoder hasn't even started // yet.) Trigger decoding so it'll be available next time. MOZ_ASSERT(aPlaybackType != PlaybackType::eAnimated || !mAnimationState || mAnimationState->KnownFrameCount() < 1, "Animated frames should be locked"); Decode(requestedSize, aFlags, aPlaybackType); // If we can sync decode, we should already have the frame. if (aFlags & FLAG_SYNC_DECODE) { result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType); } } if (!result) { // We still weren't able to get a frame. Give up. return DrawableSurface(); } if (result.Surface()->GetCompositingFailed()) { return DrawableSurface(); } MOZ_ASSERT(!result.Surface()->GetIsPaletted(), "Should not have a paletted frame"); // Sync decoding guarantees that we got the frame, but if it's owned by an // async decoder that's currently running, the contents of the frame may not // be available yet. Make sure we get everything. if (mHasSourceData && (aFlags & FLAG_SYNC_DECODE)) { result.Surface()->WaitUntilFinished(); } // If we could have done some decoding in this function we need to check if // that decoding encountered an error and hence aborted the surface. We want // to avoid calling IsAborted if we weren't passed any sync decode flag because // IsAborted acquires the monitor for the imgFrame. if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) && result.Surface()->IsAborted()) { return DrawableSurface(); } return Move(result.Surface()); }