From 368a7a51c652fe39a130ec6f09315df4f7260e53 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Fri, 20 Nov 2020 12:23:27 -0500 Subject: [PATCH] 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 --- libs/hwui/hwui/ImageDecoder.cpp | 11 ++++++++++- libs/hwui/hwui/ImageDecoder.h | 4 ++-- libs/hwui/jni/ImageDecoder.cpp | 3 ++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp index ade63e5b832c8..5d9fad5b676e1 100644 --- a/libs/hwui/hwui/ImageDecoder.cpp +++ b/libs/hwui/hwui/ImageDecoder.cpp @@ -45,7 +45,8 @@ sk_sp ImageDecoder::getDefaultColorSpace() const { return SkColorSpace::MakeSRGB(); } -ImageDecoder::ImageDecoder(std::unique_ptr codec, sk_sp peeker) +ImageDecoder::ImageDecoder(std::unique_ptr codec, sk_sp 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 codec, sk_sprewind(); + 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)) { diff --git a/libs/hwui/hwui/ImageDecoder.h b/libs/hwui/hwui/ImageDecoder.h index cbfffd5e9291d..cef2233fc3715 100644 --- a/libs/hwui/hwui/ImageDecoder.h +++ b/libs/hwui/hwui/ImageDecoder.h @@ -34,8 +34,8 @@ public: std::unique_ptr mCodec; sk_sp mPeeker; - ImageDecoder(std::unique_ptr codec, - sk_sp peeker = nullptr); + ImageDecoder(std::unique_ptr codec, sk_sp peeker = nullptr, + SkCodec::ZeroInitialized zeroInit = SkCodec::kNo_ZeroInitialized); ~ImageDecoder(); SkISize getSampledDimensions(int sampleSize) const; diff --git a/libs/hwui/jni/ImageDecoder.cpp b/libs/hwui/jni/ImageDecoder.cpp index ad7741b61e9f4..f7b8c014be6e4 100644 --- a/libs/hwui/jni/ImageDecoder.cpp +++ b/libs/hwui/jni/ImageDecoder.cpp @@ -141,7 +141,8 @@ static jobject native_create(JNIEnv* env, std::unique_ptr 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(decoder), decoder->width(), decoder->height(), animated, isNinePatch);