Bug 1427639 - Part 1. Add preferences to control image frame allocations in volatile memory or the heap. r=tnikkel

image.mem.volatile.min_threshold_kb is the minimum buffer allocation for
an image frame in KB before it will use volatile memory. If it is less
than it will use the heap. This only is set to > 0 on Android.

image.mem.animated.use_heap forces image frames to use the heap if it is
for an animated image. This is only enabled for Android, and was
previously a compile time option also for Android.
This commit is contained in:
Andrew Osmond 2018-02-22 14:26:29 -05:00
Родитель 612a195ccf
Коммит b18fc05e36
4 изменённых файлов: 58 добавлений и 22 удалений

Просмотреть файл

@ -115,6 +115,12 @@ public:
MOZ_ASSERT(mMapCount == 0);
}
bool Init(const IntSize &aSize,
SurfaceFormat aFormat,
bool aClearMem,
uint8_t aClearValue,
int32_t aStride = 0);
virtual uint8_t* GetData() override { return mArray; }
virtual int32_t Stride() override { return mStride; }
@ -142,12 +148,6 @@ public:
private:
friend class Factory;
bool Init(const IntSize &aSize,
SurfaceFormat aFormat,
bool aClearMem,
uint8_t aClearValue,
int32_t aStride = 0);
AlignedArray<uint8_t> mArray;
int32_t mStride;
SurfaceFormat mFormat;

Просмотреть файл

@ -531,11 +531,13 @@ private:
DECL_GFX_PREF(Once, "image.mem.decode_bytes_at_a_time", ImageMemDecodeBytesAtATime, uint32_t, 200000);
DECL_GFX_PREF(Live, "image.mem.discardable", ImageMemDiscardable, bool, false);
DECL_GFX_PREF(Once, "image.mem.animated.discardable", ImageMemAnimatedDiscardable, bool, false);
DECL_GFX_PREF(Live, "image.mem.animated.use_heap", ImageMemAnimatedUseHeap, bool, false);
DECL_OVERRIDE_PREF(Live, "image.mem.shared", ImageMemShared, gfxPrefs::WebRenderAll());
DECL_GFX_PREF(Once, "image.mem.surfacecache.discard_factor", ImageMemSurfaceCacheDiscardFactor, uint32_t, 1);
DECL_GFX_PREF(Once, "image.mem.surfacecache.max_size_kb", ImageMemSurfaceCacheMaxSizeKB, uint32_t, 100 * 1024);
DECL_GFX_PREF(Once, "image.mem.surfacecache.min_expiration_ms", ImageMemSurfaceCacheMinExpirationMS, uint32_t, 60*1000);
DECL_GFX_PREF(Once, "image.mem.surfacecache.size_factor", ImageMemSurfaceCacheSizeFactor, uint32_t, 64);
DECL_GFX_PREF(Live, "image.mem.volatile.min_threshold_kb", ImageMemVolatileMinThresholdKB, int32_t, -1);
DECL_GFX_PREF(Once, "image.multithreaded_decoding.limit", ImageMTDecodingLimit, int32_t, -1);
DECL_GFX_PREF(Once, "image.multithreaded_decoding.idle_timeout", ImageMTDecodingIdleTimeout, int32_t, -1);

Просмотреть файл

@ -19,6 +19,7 @@
#include "MainThreadUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/SourceSurfaceRawData.h"
#include "mozilla/layers/SourceSurfaceSharedData.h"
#include "mozilla/layers/SourceSurfaceVolatileData.h"
#include "mozilla/Likely.h"
@ -26,10 +27,6 @@
#include "nsMargin.h"
#include "nsThreadUtils.h"
#ifdef ANDROID
#define ANIMATED_FRAMES_USE_HEAP
#endif
namespace mozilla {
using namespace gfx;
@ -80,6 +77,33 @@ CreateLockedSurface(DataSourceSurface *aSurface,
return nullptr;
}
static bool
ShouldUseHeap(const IntSize& aSize,
int32_t aStride,
bool aIsAnimated)
{
// On some platforms (i.e. Android), a volatile buffer actually keeps a file
// handle active. We would like to avoid too many since we could easily
// exhaust the pool. However, 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. Hence the knobs below.
// For as long as an animated image is retained, its frames will never be
// released to let the OS purge volatile buffers.
if (aIsAnimated && gfxPrefs::ImageMemAnimatedUseHeap()) {
return true;
}
// Lets us avoid too many small images consuming all of the handles. The
// actual allocation checks for overflow.
int32_t bufferSize = (aStride * aSize.width) / 1024;
if (bufferSize < gfxPrefs::ImageMemVolatileMinThresholdKB()) {
return true;
}
return false;
}
static already_AddRefed<DataSourceSurface>
AllocateBufferForImage(const IntSize& size,
SurfaceFormat format,
@ -87,19 +111,13 @@ AllocateBufferForImage(const IntSize& size,
{
int32_t stride = VolatileSurfaceStride(size, format);
#ifdef ANIMATED_FRAMES_USE_HEAP
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::CreateDataSourceSurfaceWithStride(size, format,
stride, false);
if (ShouldUseHeap(size, stride, aIsAnimated)) {
RefPtr<SourceSurfaceAlignedRawData> newSurf =
new SourceSurfaceAlignedRawData();
if (newSurf->Init(size, format, false, 0, stride)) {
return newSurf.forget();
}
}
#endif
if (!aIsAnimated && gfxVars::GetUseWebRenderOrDefault()
&& gfxPrefs::ImageMemShared()) {

Просмотреть файл

@ -4733,6 +4733,14 @@ pref("image.mem.discardable", true);
// demand from compressed data. Has no effect if image.mem.discardable is false.
pref("image.mem.animated.discardable", true);
// Whether the heap should be used for frames from animated images. On Android,
// volatile memory keeps file handles open for each buffer.
#if defined(ANDROID)
pref("image.mem.animated.use_heap", true);
#else
pref("image.mem.animated.use_heap", false);
#endif
// Decodes images into shared memory to allow direct use in separate
// rendering processes.
pref("image.mem.shared", 2);
@ -4764,6 +4772,14 @@ pref("image.mem.surfacecache.size_factor", 4);
// and laptop systems, where we never discard visible images.
pref("image.mem.surfacecache.discard_factor", 1);
// What is the minimum buffer size in KB before using volatile memory over the
// heap. On Android, volatile memory keeps file handles open for each buffer.
#if defined(ANDROID)
pref("image.mem.volatile.min_threshold_kb", 100);
#else
pref("image.mem.volatile.min_threshold_kb", -1);
#endif
// How many threads we'll use for multithreaded decoding. If < 0, will be
// automatically determined based on the system's number of cores.
pref("image.multithreaded_decoding.limit", -1);