Bug 1370412 - Part 8a. Add "substitutable" flag to ISurfaceProvider state to indicate when the caller won't accept substitutes. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Tue, 05 Sep 2017 07:58:45 -0400
changeset 378983 c856f513264340a2d6c2b70f71f345b5e4c8d6c0
parent 378982 71f26daac945b65873a2ce99498638a9cdec0bf7
child 378984 85cdb40c26211ea3288c46927641e14f0f5661d9
push id32446
push userarchaeopteryx@coole-files.de
push dateTue, 05 Sep 2017 21:56:34 +0000
treeherdermozilla-central@f64e2b4dcf5e [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 8a. Add "substitutable" flag to ISurfaceProvider state to indicate when the caller won't accept substitutes. r=tnikkel When SurfaceCache::Lookup is called to access surface data, it indicates that the caller will not accept substitutes as in the case of SurfaceCache::LookupBestMatch. As such, we need to be careful not to remove those surfaces from our cache when pruning (in part 8b). This is the marker used to track that, at some point, there was a caller which got this surface that would accept no other (e.g. factor of 2 mode must make an accept for this particular surface).
image/DecoderFactory.cpp
image/DecoderFlags.h
image/RasterImage.cpp
image/SurfaceCache.h
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -140,16 +140,19 @@ DecoderFactory::CreateDecoder(DecoderTyp
   // Create a DecodedSurfaceProvider which will manage the decoding process and
   // make this decoder's output available in the surface cache.
   SurfaceKey surfaceKey =
     RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic);
   NotNull<RefPtr<DecodedSurfaceProvider>> provider =
     WrapNotNull(new DecodedSurfaceProvider(aImage,
                                            surfaceKey,
                                            WrapNotNull(decoder)));
+  if (aDecoderFlags & DecoderFlags::CANNOT_SUBSTITUTE) {
+    provider->Availability().SetCannotSubstitute();
+  }
 
   // Attempt to insert the surface provider into the surface cache right away so
   // we won't trigger any more decoders with the same parameters.
   if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
     return nullptr;
   }
 
   // Return the surface provider in its IDecodingTask guise.
--- a/image/DecoderFlags.h
+++ b/image/DecoderFlags.h
@@ -18,17 +18,25 @@ namespace image {
  * instead either influence which surfaces are generated at all or the tune the
  * decoder's behavior for a particular scenario.
  */
 enum class DecoderFlags : uint8_t
 {
   FIRST_FRAME_ONLY               = 1 << 0,
   IS_REDECODE                    = 1 << 1,
   IMAGE_IS_TRANSIENT             = 1 << 2,
-  ASYNC_NOTIFY                   = 1 << 3
+  ASYNC_NOTIFY                   = 1 << 3,
+
+  /**
+   * By default, a surface is considered substitutable. That means callers are
+   * willing to accept a less than ideal match to display. If a caller requires
+   * a specific size and won't accept alternatives, then this flag should be
+   * set.
+   */
+  CANNOT_SUBSTITUTE              = 1 << 4
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DecoderFlags)
 
 /**
  * @return the default set of decode flags.
  */
 inline DecoderFlags
 DefaultDecoderFlags()
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -1281,16 +1281,22 @@ RasterImage::Decode(const IntSize& aSize
     decoderFlags |= DecoderFlags::ASYNC_NOTIFY;
   }
   if (mTransient) {
     decoderFlags |= DecoderFlags::IMAGE_IS_TRANSIENT;
   }
   if (mHasBeenDecoded) {
     decoderFlags |= DecoderFlags::IS_REDECODE;
   }
+  if ((aFlags & FLAG_SYNC_DECODE) || !(aFlags & FLAG_HIGH_QUALITY_SCALING)) {
+    // Used SurfaceCache::Lookup instead of SurfaceCache::LookupBestMatch. That
+    // means the caller can handle a differently sized surface to be returned
+    // at any point.
+    decoderFlags |= DecoderFlags::CANNOT_SUBSTITUTE;
+  }
 
   SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags);
   if (IsOpaque()) {
     // If there's no transparency, it doesn't matter whether we premultiply
     // alpha or not.
     surfaceFlags &= ~SurfaceFlags::NO_PREMULTIPLY_ALPHA;
   }
 
--- a/image/SurfaceCache.h
+++ b/image/SurfaceCache.h
@@ -129,34 +129,45 @@ VectorSurfaceKey(const gfx::IntSize& aSi
  * AvailabilityState is used to track whether an ISurfaceProvider has a surface
  * available or is just a placeholder.
  *
  * To ensure that availability changes are atomic (and especially that internal
  * SurfaceCache code doesn't have to deal with asynchronous availability
  * changes), an ISurfaceProvider which starts as a placeholder can only reveal
  * the fact that it now has a surface available via a call to
  * SurfaceCache::SurfaceAvailable().
+ *
+ * It also tracks whether or not there are "explicit" users of this surface
+ * which will not accept substitutes. This is used by SurfaceCache when pruning
+ * unnecessary surfaces from the cache.
  */
 class AvailabilityState
 {
 public:
   static AvailabilityState StartAvailable() { return AvailabilityState(true); }
   static AvailabilityState StartAsPlaceholder() { return AvailabilityState(false); }
 
   bool IsAvailable() const { return mIsAvailable; }
   bool IsPlaceholder() const { return !mIsAvailable; }
+  bool CannotSubstitute() const { return mCannotSubstitute; }
+
+  void SetCannotSubstitute() { mCannotSubstitute = true; }
 
 private:
   friend class SurfaceCacheImpl;
 
-  explicit AvailabilityState(bool aIsAvailable) : mIsAvailable(aIsAvailable) { }
+  explicit AvailabilityState(bool aIsAvailable)
+    : mIsAvailable(aIsAvailable)
+    , mCannotSubstitute(false)
+  { }
 
   void SetAvailable() { mIsAvailable = true; }
 
-  bool mIsAvailable;
+  bool mIsAvailable : 1;
+  bool mCannotSubstitute : 1;
 };
 
 enum class InsertOutcome : uint8_t {
   SUCCESS,                 // Success (but see Insert documentation).
   FAILURE,                 // Couldn't insert (e.g., for capacity reasons).
   FAILURE_ALREADY_PRESENT  // A surface with the same key is already present.
 };