ImageDecoder: use kYes_ZeroInitialized memory

Bug: 183115528
Test: (A)ImageDecoderTest(s) (verify correctness)
Test: monitor showmap_pss_bytes dashboards (verify memory impact)

This lets the decoder leave zero initialized memory untouched. An
Android feature makes untouched zero initialized memory cheaper, and
BitmapFactory takes advantage of it. Do the same for ImageDecoder.

This feature was originally brought up in b/10016979. ImageDecoder saved
memory in other ways, and as I understand it, Android has shifted
towards using (Animated)VectorDrawables. Both of these may have
contributed to us not noticing when we switched from BitmapFactory to
ImageDecoder.

Change-Id: Iecfd1bbfdcc38e1f0bf380b4f4ea5b861cfcf08a
This commit is contained in:
Leon Scroggins III
2020-11-20 12:23:27 -05:00
committed by Leon Scroggins
parent 99abec3d81
commit 368a7a51c6
3 changed files with 14 additions and 4 deletions

View File

@@ -45,7 +45,8 @@ sk_sp<SkColorSpace> ImageDecoder::getDefaultColorSpace() const {
return SkColorSpace::MakeSRGB();
}
ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChunkReader> peeker)
ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChunkReader> peeker,
SkCodec::ZeroInitialized zeroInit)
: mCodec(std::move(codec))
, mPeeker(std::move(peeker))
, mDecodeSize(mCodec->codec()->dimensions())
@@ -57,6 +58,7 @@ ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChu
mTargetSize = swapWidthHeight() ? SkISize { mDecodeSize.height(), mDecodeSize.width() }
: mDecodeSize;
this->rewind();
mOptions.fZeroInitialized = zeroInit;
}
ImageDecoder::~ImageDecoder() = default;
@@ -446,10 +448,17 @@ SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) {
ALOGE("Failed to invert matrix!");
}
}
// Even if the client did not provide zero initialized memory, the
// memory we decode into is.
mOptions.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
}
auto result = mCodec->getAndroidPixels(decodeInfo, decodePixels, decodeRowBytes, &mOptions);
// The next call to decode() may not provide zero initialized memory.
mOptions.fZeroInitialized = SkCodec::kNo_ZeroInitialized;
if (scale || handleOrigin || mCropRect) {
SkBitmap scaledBm;
if (!scaledBm.installPixels(outputInfo, pixels, rowBytes)) {

View File

@@ -34,8 +34,8 @@ public:
std::unique_ptr<SkAndroidCodec> mCodec;
sk_sp<SkPngChunkReader> mPeeker;
ImageDecoder(std::unique_ptr<SkAndroidCodec> codec,
sk_sp<SkPngChunkReader> peeker = nullptr);
ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChunkReader> peeker = nullptr,
SkCodec::ZeroInitialized zeroInit = SkCodec::kNo_ZeroInitialized);
~ImageDecoder();
SkISize getSampledDimensions(int sampleSize) const;

View File

@@ -141,7 +141,8 @@ static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream,
}
const bool isNinePatch = peeker->mPatch != nullptr;
ImageDecoder* decoder = new ImageDecoder(std::move(androidCodec), std::move(peeker));
ImageDecoder* decoder = new ImageDecoder(std::move(androidCodec), std::move(peeker),
SkCodec::kYes_ZeroInitialized);
return env->NewObject(gImageDecoder_class, gImageDecoder_constructorMethodID,
reinterpret_cast<jlong>(decoder), decoder->width(), decoder->height(),
animated, isNinePatch);