Esempio n. 1
0
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;
}
Esempio n. 2
0
LookupResult
RasterImage::LookupFrameInternal(const IntSize& aSize,
                                 uint32_t aFlags,
                                 PlaybackType aPlaybackType)
{
  if (mAnimationState && aPlaybackType == PlaybackType::eAnimated) {
    MOZ_ASSERT(mFrameAnimator);
    MOZ_ASSERT(ToSurfaceFlags(aFlags) == DefaultSurfaceFlags(),
               "Can't composite frames with non-default surface flags");
    const size_t index = mAnimationState->GetCurrentAnimationFrameIndex();
    return mFrameAnimator->GetCompositedFrame(index);
  }

  SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags);

  // We don't want any substitution for sync decodes, and substitution would be
  // illegal when high quality downscaling is disabled, so we use
  // SurfaceCache::Lookup in this case.
  if ((aFlags & FLAG_SYNC_DECODE) || !(aFlags & FLAG_HIGH_QUALITY_SCALING)) {
    return SurfaceCache::Lookup(ImageKey(this),
                                RasterSurfaceKey(aSize,
                                                 surfaceFlags,
                                                 PlaybackType::eStatic));
  }

  // We'll return the best match we can find to the requested frame.
  return SurfaceCache::LookupBestMatch(ImageKey(this),
                                       RasterSurfaceKey(aSize,
                                                        surfaceFlags,
                                                        PlaybackType::eStatic));
}
Esempio n. 3
0
RasterImage::WillDrawOpaqueNow()
{
  if (!IsOpaque()) {
    return false;
  }

  if (mAnimationState) {
    // We never discard frames of animated images.
    return true;
  }

  // If we are not locked our decoded data could get discard at any time (ie
  // between the call to this function and when we are asked to draw), so we
  // have to return false if we are unlocked.
  if (IsUnlocked()) {
    return false;
  }

  LookupResult result =
    SurfaceCache::LookupBestMatch(ImageKey(this),
                                  RasterSurfaceKey(mSize,
                                                   DefaultSurfaceFlags(),
                                                   PlaybackType::eStatic));
  MatchType matchType = result.Type();
  if (matchType == MatchType::NOT_FOUND || matchType == MatchType::PENDING ||
      !result.Surface()->IsFinished()) {
    return false;
  }

  return true;
}
Esempio n. 4
0
RawAccessFrameRef
FrameAnimator::GetRawFrame(uint32_t aFrameNum) const
{
  LookupResult result =
    SurfaceCache::Lookup(ImageKey(mImage),
                         RasterSurfaceKey(mSize,
                                          DefaultSurfaceFlags(),
                                          aFrameNum));
  return result ? result.DrawableRef()->RawAccessRef()
                : RawAccessFrameRef();
}
Esempio n. 5
0
RawAccessFrameRef
FrameAnimator::GetRawFrame(uint32_t aFrameNum) const
{
  LookupResult result =
    SurfaceCache::Lookup(ImageKey(mImage),
                         RasterSurfaceKey(mSize,
                                          DefaultSurfaceFlags(),
                                          PlaybackType::eAnimated));
  if (!result) {
    return RawAccessFrameRef();
  }

  // Seek to the frame we want. If seeking fails, it means we couldn't get the
  // frame we're looking for, so we bail here to avoid returning the wrong frame
  // to the caller.
  if (NS_FAILED(result.Surface().Seek(aFrameNum))) {
    return RawAccessFrameRef();  // Not available yet.
  }

  return result.Surface()->RawAccessRef();
}
Esempio n. 6
0
LookupResult
FrameAnimator::GetCompositedFrame(uint32_t aFrameNum)
{
  MOZ_ASSERT(aFrameNum != 0, "First frame is never composited");

  // If we have a composited version of this frame, return that.
  if (mLastCompositedFrameIndex == int32_t(aFrameNum)) {
    return LookupResult(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(),
                                          aFrameNum));
  MOZ_ASSERT(!result || !result.DrawableRef()->GetIsPaletted(),
             "About to return a paletted frame");
  return result;
}
Esempio n. 7
0
Decoder::Decoder(RasterImage* aImage)
  : mImageData(nullptr)
  , mImageDataLength(0)
  , mColormap(nullptr)
  , mColormapSize(0)
  , mImage(aImage)
  , mProgress(NoProgress)
  , mFrameCount(0)
  , mFailCode(NS_OK)
  , mChunkCount(0)
  , mDecoderFlags(DefaultDecoderFlags())
  , mSurfaceFlags(DefaultSurfaceFlags())
  , mBytesDecoded(0)
  , mInitialized(false)
  , mMetadataDecode(false)
  , mInFrame(false)
  , mDataDone(false)
  , mDecodeDone(false)
  , mDataError(false)
  , mDecodeAborted(false)
  , mShouldReportError(false)
{ }
Esempio n. 8
0
void
RasterImage::NotifyProgress(Progress aProgress,
                            const IntRect& aInvalidRect /* = IntRect() */,
                            const Maybe<uint32_t>& aFrameCount /* = Nothing() */,
                            DecoderFlags aDecoderFlags
                              /* = DefaultDecoderFlags() */,
                            SurfaceFlags aSurfaceFlags
                              /* = DefaultSurfaceFlags() */)
{
  MOZ_ASSERT(NS_IsMainThread());

  // Ensure that we stay alive long enough to finish notifying.
  RefPtr<RasterImage> image = this;

  const bool wasDefaultFlags = aSurfaceFlags == DefaultSurfaceFlags();

  if (!aInvalidRect.IsEmpty() && wasDefaultFlags) {
    // Update our image container since we're invalidating.
    UpdateImageContainer();
  }

  if (!(aDecoderFlags & DecoderFlags::FIRST_FRAME_ONLY)) {
    // We may have decoded new animation frames; update our animation state.
    MOZ_ASSERT_IF(aFrameCount && *aFrameCount > 1, mAnimationState || mError);
    if (mAnimationState && aFrameCount) {
      mAnimationState->UpdateKnownFrameCount(*aFrameCount);
    }

    // If we should start animating right now, do so.
    if (mAnimationState && aFrameCount == Some(1u) &&
        mPendingAnimation && ShouldAnimate()) {
      StartAnimation();
    }
  }

  // Tell the observers what happened.
  image->mProgressTracker->SyncNotifyProgress(aProgress, aInvalidRect);
}
Esempio n. 9
0
static void
DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface,
                                   SurfaceMemoryCounterType aType,
                                   nsTArray<SurfaceMemoryCounter>& aCounters,
                                   MallocSizeOf aMallocSizeOf)
{
  // Concoct a SurfaceKey for this surface.
  SurfaceKey key = RasterSurfaceKey(aSurface->GetImageSize(),
                                    DefaultSurfaceFlags(),
                                    PlaybackType::eStatic);

  // Create a counter for this surface.
  SurfaceMemoryCounter counter(key, /* aIsLocked = */ true, aType);

  // Extract the surface's memory usage information.
  size_t heap = 0, nonHeap = 0;
  aSurface->AddSizeOfExcludingThis(aMallocSizeOf, heap, nonHeap);
  counter.Values().SetDecodedHeap(heap);
  counter.Values().SetDecodedNonHeap(nonHeap);

  // Record it.
  aCounters.AppendElement(counter);
}
Esempio n. 10
0
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;
}