Bug 1383499 - Animated PNGs should allocate after-first frames on the heap instead of as volatile buffers on Android. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Wed, 16 Aug 2017 08:57:40 -0400
changeset 427092 edd9d2acbac76a37a0c5ee63f908cc2ba8fb239d
parent 427091 11f8164a517656429af540f4e04f88db71d0c3ba
child 427093 a9f759fd05fd7b92070a73f722cc0f51aee17080
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1383499
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 1383499 - Animated PNGs should allocate after-first frames on the heap instead of as volatile buffers on Android. r=tnikkel Animated image frames are never actually released to let the OS purge them, because AnimationSurfaceProvider keeps them as RawAccessFrameRef. Meanwhile, each volatile buffer on Android needs a file handle to be retained for as long as the buffer lives. Given sufficient number of animated image frames, we could easily exhaust the available file handles (which in turn causes many problems). As such on Android we should stick with the heap for animated image frames. On other platforms it is better to stay because we will avoid a memset, because the OS will zero-fill the requested pages on our behalf.
image/imgFrame.cpp
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -78,16 +78,29 @@ CreateLockedSurface(DataSourceSurface *a
   return nullptr;
 }
 
 static already_AddRefed<DataSourceSurface>
 AllocateBufferForImage(const IntSize& size,
                        SurfaceFormat format,
                        bool aIsAnimated = false)
 {
+#ifdef ANDROID
+  if (aIsAnimated) {
+    // For as long as an animated image is retained, its frames will never be
+    // released to let the OS purge volatile buffers. On Android, a volatile
+    // buffer actually keeps a file handle active, which we would like to avoid
+    // since many images and frames could easily exhaust the pool. As such, we
+    // use the heap. On the other platforms we do not have the file handle
+    // problem, and additionally we may avoid a superfluous memset since the
+    // volatile memory starts out as zero-filled.
+    return Factory::CreateDataSourceSurface(size, format, false);
+  }
+#endif
+
   int32_t stride = VolatileSurfaceStride(size, format);
   if (!aIsAnimated && gfxPrefs::ImageMemShared()) {
     RefPtr<SourceSurfaceSharedData> newSurf = new SourceSurfaceSharedData();
     if (newSurf->Init(size, stride, format)) {
       return newSurf.forget();
     }
   } else {
     RefPtr<SourceSurfaceVolatileData> newSurf= new SourceSurfaceVolatileData();