Merge "Report native allocation size of AnimatedImageDrawable" into pi-dev am: d848f75f99
am: 6413aebc02
Change-Id: Id1a101b08f8f9b9b53875bd9c784dea04a5b4110
This commit is contained in:
@@ -42,7 +42,6 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
|
||||
}
|
||||
|
||||
auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder);
|
||||
auto info = imageDecoder->mCodec->getInfo();
|
||||
const SkISize scaledSize = SkISize::Make(width, height);
|
||||
SkIRect subset;
|
||||
if (jsubset) {
|
||||
@@ -51,6 +50,35 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
|
||||
subset = SkIRect::MakeWH(width, height);
|
||||
}
|
||||
|
||||
auto info = imageDecoder->mCodec->getInfo();
|
||||
bool hasRestoreFrame = false;
|
||||
if (imageDecoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kWEBP) {
|
||||
if (width < info.width() && height < info.height()) {
|
||||
// WebP will scale its SkBitmap to the scaled size.
|
||||
// FIXME: b/73529447 GIF should do the same.
|
||||
info = info.makeWH(width, height);
|
||||
}
|
||||
} else {
|
||||
const int frameCount = imageDecoder->mCodec->codec()->getFrameCount();
|
||||
for (int i = 0; i < frameCount; ++i) {
|
||||
SkCodec::FrameInfo frameInfo;
|
||||
if (!imageDecoder->mCodec->codec()->getFrameInfo(i, &frameInfo)) {
|
||||
doThrowIOE(env, "Failed to read frame info!");
|
||||
return 0;
|
||||
}
|
||||
if (frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
|
||||
hasRestoreFrame = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t bytesUsed = info.computeMinByteSize();
|
||||
// SkAnimatedImage has one SkBitmap for decoding, plus an extra one if there is a
|
||||
// kRestorePrevious frame. AnimatedImageDrawable has two SkPictures storing the current
|
||||
// frame and the next frame. (The former assumes that the image is animated, and the
|
||||
// latter assumes that it is drawn to a hardware canvas.)
|
||||
bytesUsed *= hasRestoreFrame ? 4 : 3;
|
||||
sk_sp<SkPicture> picture;
|
||||
if (jpostProcess) {
|
||||
SkRect bounds = SkRect::MakeWH(subset.width(), subset.height());
|
||||
@@ -63,6 +91,7 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
|
||||
return 0;
|
||||
}
|
||||
picture = recorder.finishRecordingAsPicture();
|
||||
bytesUsed += picture->approximateBytesUsed();
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +103,10 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
|
||||
return 0;
|
||||
}
|
||||
|
||||
sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(animatedImg));
|
||||
bytesUsed += sizeof(animatedImg.get());
|
||||
|
||||
sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(std::move(animatedImg),
|
||||
bytesUsed));
|
||||
return reinterpret_cast<jlong>(drawable.release());
|
||||
}
|
||||
|
||||
@@ -202,10 +234,9 @@ static void AnimatedImageDrawable_nSetOnAnimationEndListener(JNIEnv* env, jobjec
|
||||
}
|
||||
}
|
||||
|
||||
static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
|
||||
static jlong AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
|
||||
auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
|
||||
// FIXME: Report the size of the internal SkBitmap etc.
|
||||
return sizeof(drawable);
|
||||
return drawable->byteSize();
|
||||
}
|
||||
|
||||
static void AnimatedImageDrawable_nMarkInvisible(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
|
||||
|
||||
@@ -292,8 +292,7 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 {
|
||||
mState = new State(nCreate(nativeImageDecoder, decoder, width, height, cropRect),
|
||||
inputStream, afd);
|
||||
|
||||
// FIXME: Use the right size for the native allocation.
|
||||
long nativeSize = 200;
|
||||
final long nativeSize = nNativeByteSize(mState.mNativePtr);
|
||||
NativeAllocationRegistry registry = new NativeAllocationRegistry(
|
||||
AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
|
||||
registry.registerNativeAllocation(mState, mState.mNativePtr);
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage)
|
||||
: mSkAnimatedImage(std::move(animatedImage)) {
|
||||
AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
|
||||
: mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) {
|
||||
mTimeToShowNextSnapshot = mSkAnimatedImage->currentFrameDuration();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,9 @@ public:
|
||||
*/
|
||||
class ANDROID_API AnimatedImageDrawable : public SkDrawable {
|
||||
public:
|
||||
AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage);
|
||||
// bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the
|
||||
// Snapshots.
|
||||
AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed);
|
||||
|
||||
/**
|
||||
* This updates the internal time and returns true if the animation needs
|
||||
@@ -100,11 +102,17 @@ public:
|
||||
Snapshot decodeNextFrame();
|
||||
Snapshot reset();
|
||||
|
||||
size_t byteSize() const {
|
||||
return sizeof(this) + mBytesUsed;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onDraw(SkCanvas* canvas) override;
|
||||
|
||||
private:
|
||||
sk_sp<SkAnimatedImage> mSkAnimatedImage;
|
||||
const size_t mBytesUsed;
|
||||
|
||||
bool mRunning = false;
|
||||
bool mStarting = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user