bool RasterImage::StartDecodingWithResult(uint32_t aFlags) { if (mError) { return false; } if (!mHasSize) { mWantFullDecode = true; return false; } uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST; DrawableSurface surface = RequestDecodeForSizeInternal(mSize, flags); return surface && surface->IsFinished(); }
Pair<DrawResult, RefPtr<SourceSurface>> RasterImage::GetFrameInternal(const IntSize& aSize, uint32_t aWhichFrame, uint32_t aFlags) { MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE); if (aSize.IsEmpty()) { return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>()); } if (aWhichFrame > FRAME_MAX_VALUE) { return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>()); } if (mError) { return MakePair(DrawResult::BAD_IMAGE, RefPtr<SourceSurface>()); } // Get the frame. If it's not there, it's probably the caller's fault for // not waiting for the data to be loaded from the network or not passing // FLAG_SYNC_DECODE. DrawableSurface surface = LookupFrame(aSize, aFlags, ToPlaybackType(aWhichFrame)); if (!surface) { // The OS threw this frame away and we couldn't redecode it. return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>()); } RefPtr<SourceSurface> sourceSurface = surface->GetSourceSurface(); if (!surface->IsFinished()) { return MakePair(DrawResult::INCOMPLETE, Move(sourceSurface)); } return MakePair(DrawResult::SUCCESS, Move(sourceSurface)); }
RasterImage::Draw(gfxContext* aContext, const IntSize& aSize, const ImageRegion& aRegion, uint32_t aWhichFrame, SamplingFilter aSamplingFilter, const Maybe<SVGImageContext>& /*aSVGContext - ignored*/, uint32_t aFlags) { if (aWhichFrame > FRAME_MAX_VALUE) { return DrawResult::BAD_ARGS; } if (mError) { return DrawResult::BAD_IMAGE; } // Illegal -- you can't draw with non-default decode flags. // (Disabling colorspace conversion might make sense to allow, but // we don't currently.) if (ToSurfaceFlags(aFlags) != DefaultSurfaceFlags()) { return DrawResult::BAD_ARGS; } if (!aContext) { return DrawResult::BAD_ARGS; } if (IsUnlocked() && mProgressTracker) { mProgressTracker->OnUnlockedDraw(); } // If we're not using SamplingFilter::GOOD, we shouldn't high-quality scale or // downscale during decode. uint32_t flags = aSamplingFilter == SamplingFilter::GOOD ? aFlags : aFlags & ~FLAG_HIGH_QUALITY_SCALING; DrawableSurface surface = LookupFrame(aSize, flags, ToPlaybackType(aWhichFrame)); if (!surface) { // Getting the frame (above) touches the image and kicks off decoding. if (mDrawStartTime.IsNull()) { mDrawStartTime = TimeStamp::Now(); } return DrawResult::NOT_READY; } bool shouldRecordTelemetry = !mDrawStartTime.IsNull() && surface->IsFinished(); auto result = DrawInternal(Move(surface), aContext, aSize, aRegion, aSamplingFilter, flags); if (shouldRecordTelemetry) { TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime; Telemetry::Accumulate(Telemetry::IMAGE_DECODE_ON_DRAW_LATENCY, int32_t(drawLatency.ToMicroseconds())); mDrawStartTime = TimeStamp(); } return result; }