Bug 1370412 - Part 2. Give image::LookupResult an optional preferred size to decode at when the surface is not found. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Tue, 05 Sep 2017 07:58:45 -0400
changeset 428461 87b213841ad3a681dcca9183e033c4281d9a867d
parent 428460 b9e5d359e10e0700cec1a04bff36b4b11d6ccfa0
child 428462 4f0c916b3960dd3a740286a92853180b1e7de9c0
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1370412
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1370412 - Part 2. Give image::LookupResult an optional preferred size to decode at when the surface is not found. r=tnikkel
image/LookupResult.h
image/RasterImage.cpp
--- a/image/LookupResult.h
+++ b/image/LookupResult.h
@@ -7,30 +7,38 @@
  * LookupResult is the return type of SurfaceCache's Lookup*() functions. It
  * combines a surface with relevant metadata tracked by SurfaceCache.
  */
 
 #ifndef mozilla_image_LookupResult_h
 #define mozilla_image_LookupResult_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/gfx/Point.h"  // for IntSize
 #include "mozilla/Move.h"
 #include "ISurfaceProvider.h"
 
 namespace mozilla {
 namespace image {
 
 enum class MatchType : uint8_t
 {
   NOT_FOUND,  // No matching surface and no placeholder.
   PENDING,    // Found a matching placeholder, but no surface.
   EXACT,      // Found a surface that matches exactly.
   SUBSTITUTE_BECAUSE_NOT_FOUND,  // No exact match, but found a similar one.
-  SUBSTITUTE_BECAUSE_PENDING     // Found a similar surface and a placeholder
+  SUBSTITUTE_BECAUSE_PENDING,    // Found a similar surface and a placeholder
                                  // for an exact match.
+
+  /* No exact match, but this should be considered an exact match for purposes
+   * of deciding whether or not to request a new decode. This is because the
+   * cache has determined that callers require too many size variants of this
+   * image. It determines the set of sizes which best represent the image, and
+   * will only suggest decoding of unavailable sizes from that set. */
+  SUBSTITUTE_BECAUSE_BEST
 };
 
 /**
  * LookupResult is the return type of SurfaceCache's Lookup*() functions. It
  * combines a surface with relevant metadata tracked by SurfaceCache.
  */
 class MOZ_STACK_CLASS LookupResult
 {
@@ -55,36 +63,55 @@ public:
     MOZ_ASSERT(!mSurface || !(mMatchType == MatchType::NOT_FOUND ||
                               mMatchType == MatchType::PENDING),
                "Only NOT_FOUND or PENDING make sense with no surface");
     MOZ_ASSERT(mSurface || mMatchType == MatchType::NOT_FOUND ||
                            mMatchType == MatchType::PENDING,
                "NOT_FOUND or PENDING do not make sense with a surface");
   }
 
+  LookupResult(DrawableSurface&& aSurface, MatchType aMatchType,
+               const gfx::IntSize& aSuggestedSize)
+    : mSurface(Move(aSurface))
+    , mMatchType(aMatchType)
+    , mSuggestedSize(aSuggestedSize)
+  {
+    MOZ_ASSERT(!mSuggestedSize.IsEmpty());
+    MOZ_ASSERT(!mSurface || aMatchType == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND,
+               "Only SUBSTITUTE_BECAUSE_NOT_FOUND make sense with no surface");
+    MOZ_ASSERT(mSurface || aMatchType == MatchType::NOT_FOUND,
+               "NOT_FOUND does not make sense with a surface");
+  }
+
   LookupResult& operator=(LookupResult&& aOther)
   {
     MOZ_ASSERT(&aOther != this, "Self-move-assignment is not supported");
     mSurface = Move(aOther.mSurface);
     mMatchType = aOther.mMatchType;
+    mSuggestedSize = aOther.mSuggestedSize;
     return *this;
   }
 
   DrawableSurface& Surface() { return mSurface; }
   const DrawableSurface& Surface() const { return mSurface; }
+  const gfx::IntSize& SuggestedSize() const { return mSuggestedSize; }
 
   /// @return true if this LookupResult contains a surface.
   explicit operator bool() const { return bool(mSurface); }
 
   /// @return what kind of match this is (exact, substitute, etc.)
   MatchType Type() const { return mMatchType; }
 
 private:
   LookupResult(const LookupResult&) = delete;
 
   DrawableSurface mSurface;
   MatchType mMatchType;
+
+  /// If given, the size the caller should request a decode at. This may or may
+  /// not match the size the caller requested from the cache.
+  gfx::IntSize mSuggestedSize;
 };
 
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_LookupResult_h
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -361,16 +361,24 @@ RasterImage::LookupFrame(const IntSize& 
     // 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 ||
                gfxPrefs::ImageMemAnimatedDiscardable() ||
                !mAnimationState || mAnimationState->KnownFrameCount() < 1,
                "Animated frames should be locked");
 
+    // The surface cache may suggest the preferred size we are supposed to
+    // decode at. This should only happen if we accept substitutions.
+    if (!result.SuggestedSize().IsEmpty()) {
+      MOZ_ASSERT(!(aFlags & FLAG_SYNC_DECODE) &&
+                  (aFlags & FLAG_HIGH_QUALITY_SCALING));
+      requestedSize = result.SuggestedSize();
+    }
+
     bool ranSync = Decode(requestedSize, aFlags, aPlaybackType);
 
     // If we can or did sync decode, we should already have the frame.
     if (ranSync || (aFlags & FLAG_SYNC_DECODE)) {
       result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType);
     }
   }