xref: /aosp_15_r20/frameworks/base/libs/hwui/hwui/AnimatedImageDrawable.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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 <SkAnimatedImage.h>
20 #include <SkCanvas.h>
21 #include <SkColorFilter.h>
22 #include <SkDrawable.h>
23 #include <SkEncodedImageFormat.h>
24 #include <SkPicture.h>
25 #include <cutils/compiler.h>
26 #include <utils/Macros.h>
27 #include <utils/RefBase.h>
28 #include <utils/Timers.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 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                           SkEncodedImageFormat format);
53 
54     /**
55      * This updates the internal time and returns true if the image needs
56      * to be redrawn this frame.
57      *
58      * This is called on RenderThread, while the UI thread is locked.
59      *
60      * @param outDelay Nanoseconds in the future when the following frame
61      *      will need to be drawn. 0 if not running.
62      */
63     bool isDirty(nsecs_t* outDelay);
64 
getStagingAlpha()65     int getStagingAlpha() const { return mStagingProperties.mAlpha; }
setStagingAlpha(int alpha)66     void setStagingAlpha(int alpha) { mStagingProperties.mAlpha = alpha; }
setStagingColorFilter(sk_sp<SkColorFilter> filter)67     void setStagingColorFilter(sk_sp<SkColorFilter> filter) {
68         mStagingProperties.mColorFilter = filter;
69     }
setStagingMirrored(bool mirrored)70     void setStagingMirrored(bool mirrored) { mStagingProperties.mMirrored = mirrored; }
setStagingBounds(const SkRect & bounds)71     void setStagingBounds(const SkRect& bounds) { mStagingProperties.mBounds = bounds; }
72     void syncProperties();
73 
74     SkRect onGetBounds() override;
75 
76     // Draw to software canvas, and return time to next draw.
77     // 0 means the animation is not running.
78     // -1 means the animation advanced to the final frame.
79     int drawStaging(SkCanvas* canvas);
80 
81     // Returns true if the animation was started; false otherwise (e.g. it was
82     // already running)
83     bool start();
84     // Returns true if the animation was stopped; false otherwise (e.g. it was
85     // already stopped)
86     bool stop();
87     bool isRunning();
getRepetitionCount()88     int getRepetitionCount() const { return mSkAnimatedImage->getRepetitionCount(); }
setRepetitionCount(int count)89     void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); }
90     // Returns true if the filter mode is set to linear sampling; false if it is
91     // set to nearest neighbor sampling.
92     bool getFilterBitmap() const;
93     // Returns true if the filter mode was changed; false otherwise.
94     bool setFilterBitmap(bool filterBitmap);
95 
setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener)96     void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) {
97         mEndListener = std::move(listener);
98     }
99 
100     struct Snapshot {
101         sk_sp<SkPicture> mPic;
102         int mDurationMS;
103 
104         Snapshot() = default;
105 
106         Snapshot(Snapshot&&) = default;
107         Snapshot& operator=(Snapshot&&) = default;
108 
109         PREVENT_COPY_AND_ASSIGN(Snapshot);
110     };
111 
112     // These are only called on AnimatedImageThread.
113     Snapshot decodeNextFrame();
114     Snapshot reset();
115 
byteSize()116     size_t byteSize() const { return sizeof(*this) + mBytesUsed; }
117 
118 protected:
119     void onDraw(SkCanvas* canvas) override;
120 
121 private:
122     sk_sp<SkAnimatedImage> mSkAnimatedImage;
123     const size_t mBytesUsed;
124     const SkEncodedImageFormat mFormat;
125 
126     bool mRunning = false;
127     bool mStarting = false;
128 
129     // A snapshot of the current frame to draw.
130     Snapshot mSnapshot;
131 
132     std::future<Snapshot> mNextSnapshot;
133 
134     bool nextSnapshotReady() const;
135 
136     // When to switch from mSnapshot to mNextSnapshot.
137     nsecs_t mTimeToShowNextSnapshot = 0;
138 
139     // The current time for the drawable itself.
140     nsecs_t mCurrentTime = 0;
141 
142     // The wall clock of the last time we called isDirty.
143     nsecs_t mLastWallTime = 0;
144 
145     // Locked when assigning snapshots and times. Operations while this is held
146     // should be short.
147     std::mutex mSwapLock;
148 
149     // Locked when mSkAnimatedImage is being updated or drawn.
150     std::mutex mImageLock;
151 
152     struct Properties {
153         int mAlpha = SK_AlphaOPAQUE;
154         sk_sp<SkColorFilter> mColorFilter;
155         bool mMirrored = false;
156         SkRect mBounds;
157 
158         Properties() = default;
159         Properties(Properties&) = default;
160         Properties& operator=(Properties&) = default;
161     };
162 
163     Properties mStagingProperties;
164     Properties mProperties;
165 
166     std::unique_ptr<OnAnimationEndListener> mEndListener;
167 
168     int adjustFrameDuration(int);
169     int currentFrameDuration();
170 };
171 
172 }  // namespace android
173