1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cutils/compiler.h> 20 #include <utils/Macros.h> 21 #include <utils/RefBase.h> 22 #include <utils/Timers.h> 23 24 #include <SkAnimatedImage.h> 25 #include <SkCanvas.h> 26 #include <SkColorFilter.h> 27 #include <SkDrawable.h> 28 #include <SkPicture.h> 29 30 #include <future> 31 #include <mutex> 32 33 namespace android { 34 35 class OnAnimationEndListener { 36 public: ~OnAnimationEndListener()37 virtual ~OnAnimationEndListener() {} 38 39 virtual void onAnimationEnd() = 0; 40 }; 41 42 /** 43 * Native component of android.graphics.drawable.AnimatedImageDrawables.java. 44 * This class can be drawn into Canvas.h and maintains the state needed to drive 45 * the animation from the RenderThread. 46 */ 47 class ANDROID_API AnimatedImageDrawable : public SkDrawable { 48 public: 49 // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the 50 // Snapshots. 51 AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed); 52 53 /** 54 * This updates the internal time and returns true if the image needs 55 * to be redrawn this frame. 56 * 57 * This is called on RenderThread, while the UI thread is locked. 58 * 59 * @param outDelay Nanoseconds in the future when the following frame 60 * will need to be drawn. 0 if not running. 61 */ 62 bool isDirty(nsecs_t* outDelay); 63 getStagingAlpha()64 int getStagingAlpha() const { return mStagingProperties.mAlpha; } setStagingAlpha(int alpha)65 void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; } setStagingColorFilter(sk_sp<SkColorFilter> filter)66 void setStagingColorFilter(sk_sp<SkColorFilter> filter) { 67 mStagingProperties.mColorFilter = filter; 68 } setStagingMirrored(bool mirrored)69 void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; } 70 void syncProperties(); 71 onGetBounds()72 virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); } 73 74 // Draw to software canvas, and return time to next draw. 75 // 0 means the animation is not running. 76 // -1 means the animation advanced to the final frame. 77 int drawStaging(SkCanvas* canvas); 78 79 // Returns true if the animation was started; false otherwise (e.g. it was 80 // already running) 81 bool start(); 82 // Returns true if the animation was stopped; false otherwise (e.g. it was 83 // already stopped) 84 bool stop(); 85 bool isRunning(); getRepetitionCount()86 int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); } setRepetitionCount(int count)87 void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); } 88 setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener)89 void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) { 90 mEndListener = std::move(listener); 91 } 92 93 struct Snapshot { 94 sk_sp<SkPicture> mPic; 95 int mDurationMS; 96 97 Snapshot() = default; 98 99 Snapshot(Snapshot&&) = default; 100 Snapshot& operator=(Snapshot&&) = default; 101 102 PREVENT_COPY_AND_ASSIGN(Snapshot); 103 }; 104 105 // These are only called on AnimatedImageThread. 106 Snapshot decodeNextFrame(); 107 Snapshot reset(); 108 byteSize()109 size_t byteSize() const { return sizeof(*this) + mBytesUsed; } 110 111 protected: 112 virtual void onDraw(SkCanvas* canvas) override; 113 114 private: 115 sk_sp<SkAnimatedImage> mSkAnimatedImage; 116 const size_t mBytesUsed; 117 118 bool mRunning = false; 119 bool mStarting = false; 120 121 // A snapshot of the current frame to draw. 122 Snapshot mSnapshot; 123 124 std::future<Snapshot> mNextSnapshot; 125 126 bool nextSnapshotReady() const; 127 128 // When to switch from mSnapshot to mNextSnapshot. 129 nsecs_t mTimeToShowNextSnapshot = 0; 130 131 // The current time for the drawable itself. 132 nsecs_t mCurrentTime = 0; 133 134 // The wall clock of the last time we called isDirty. 135 nsecs_t mLastWallTime = 0; 136 137 // Locked when assigning snapshots and times. Operations while this is held 138 // should be short. 139 std::mutex mSwapLock; 140 141 // Locked when mSkAnimatedImage is being updated or drawn. 142 std::mutex mImageLock; 143 144 struct Properties { 145 int mAlpha = SK_AlphaOPAQUE; 146 sk_sp<SkColorFilter> mColorFilter; 147 bool mMirrored = false; 148 149 Properties() = default; 150 Properties(Properties&) = default; 151 Properties& operator=(Properties&) = default; 152 }; 153 154 Properties mStagingProperties; 155 Properties mProperties; 156 157 std::unique_ptr<OnAnimationEndListener> mEndListener; 158 }; 159 160 } // namespace android 161