1 /*
2  * Copyright 2019 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 #include <algorithm>
18 
19 #include <common/FlagManager.h>
20 #include "Client.h"
21 #include "Layer.h"
22 #include "RefreshRateOverlay.h"
23 
24 #include <SkSurface.h>
25 
26 #undef LOG_TAG
27 #define LOG_TAG "RefreshRateOverlay"
28 
29 namespace android {
30 
draw(int refreshRate,int renderFps,bool idle,SkColor color,ui::Transform::RotationFlags rotation,ftl::Flags<Features> features)31 auto RefreshRateOverlay::draw(int refreshRate, int renderFps, bool idle, SkColor color,
32                               ui::Transform::RotationFlags rotation, ftl::Flags<Features> features)
33         -> Buffers {
34     const size_t loopCount = features.test(Features::Spinner) ? 6 : 1;
35     const bool isSetByHwc = features.test(Features::SetByHwc);
36 
37     Buffers buffers;
38     buffers.reserve(loopCount);
39 
40     for (size_t i = 0; i < loopCount; i++) {
41         // Pre-rotate the buffer before it reaches SurfaceFlinger.
42         SkMatrix canvasTransform = SkMatrix();
43         const auto [bufferWidth, bufferHeight] = [&]() -> std::pair<int, int> {
44             switch (rotation) {
45                 case ui::Transform::ROT_90:
46                     canvasTransform.setTranslate(kBufferHeight, 0);
47                     canvasTransform.preRotate(90.f);
48                     return {kBufferHeight, kBufferWidth};
49                 case ui::Transform::ROT_270:
50                     canvasTransform.setRotate(270.f, kBufferWidth / 2.f, kBufferWidth / 2.f);
51                     return {kBufferHeight, kBufferWidth};
52                 default:
53                     return {kBufferWidth, kBufferHeight};
54             }
55         }();
56 
57         const auto kUsageFlags =
58                 static_cast<uint64_t>(GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER |
59                                       GRALLOC_USAGE_HW_TEXTURE);
60         sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(static_cast<uint32_t>(bufferWidth),
61                                                            static_cast<uint32_t>(bufferHeight),
62                                                            HAL_PIXEL_FORMAT_RGBA_8888, 1u,
63                                                            kUsageFlags, "RefreshRateOverlayBuffer");
64 
65         const status_t bufferStatus = buffer->initCheck();
66         LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "RefreshRateOverlay: Buffer failed to allocate: %d",
67                             bufferStatus);
68 
69         sk_sp<SkSurface> surface = SkSurfaces::Raster(
70                 SkImageInfo::MakeN32Premul(bufferWidth, bufferHeight));
71         SkCanvas* canvas = surface->getCanvas();
72         canvas->setMatrix(canvasTransform);
73 
74         int left = 0;
75         if (idle && !isSetByHwc) {
76             drawDash(left, *canvas);
77         } else {
78             drawNumber(refreshRate, left, color, *canvas);
79         }
80         left += 3 * (kDigitWidth + kDigitSpace);
81         if (features.test(Features::Spinner)) {
82             switch (i) {
83                 case 0:
84                     SegmentDrawer::drawSegment(SegmentDrawer::Segment::Upper, left, color, *canvas);
85                     break;
86                 case 1:
87                     SegmentDrawer::drawSegment(SegmentDrawer::Segment::UpperRight, left, color,
88                                                *canvas);
89                     break;
90                 case 2:
91                     SegmentDrawer::drawSegment(SegmentDrawer::Segment::LowerRight, left, color,
92                                                *canvas);
93                     break;
94                 case 3:
95                     SegmentDrawer::drawSegment(SegmentDrawer::Segment::Bottom, left, color,
96                                                *canvas);
97                     break;
98                 case 4:
99                     SegmentDrawer::drawSegment(SegmentDrawer::Segment::LowerLeft, left, color,
100                                                *canvas);
101                     break;
102                 case 5:
103                     SegmentDrawer::drawSegment(SegmentDrawer::Segment::UpperLeft, left, color,
104                                                *canvas);
105                     break;
106             }
107         }
108 
109         left += kDigitWidth + kDigitSpace;
110 
111         if (features.test(Features::RenderRate)) {
112             if (idle) {
113                 drawDash(left, *canvas);
114             } else {
115                 drawNumber(renderFps, left, color, *canvas);
116             }
117         }
118         left += 3 * (kDigitWidth + kDigitSpace);
119 
120         void* pixels = nullptr;
121         buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
122 
123         const SkImageInfo& imageInfo = surface->imageInfo();
124         const size_t dstRowBytes =
125                 buffer->getStride() * static_cast<size_t>(imageInfo.bytesPerPixel());
126 
127         canvas->readPixels(imageInfo, pixels, dstRowBytes, 0, 0);
128         buffer->unlock();
129         buffers.push_back(std::move(buffer));
130     }
131     return buffers;
132 }
133 
drawNumber(int number,int left,SkColor color,SkCanvas & canvas)134 void RefreshRateOverlay::drawNumber(int number, int left, SkColor color, SkCanvas& canvas) {
135     if (number < 0 || number >= 1000) return;
136 
137     if (number >= 100) {
138         SegmentDrawer::drawDigit(number / 100, left, color, canvas);
139     }
140     left += kDigitWidth + kDigitSpace;
141 
142     if (number >= 10) {
143         SegmentDrawer::drawDigit((number / 10) % 10, left, color, canvas);
144     }
145     left += kDigitWidth + kDigitSpace;
146 
147     SegmentDrawer::drawDigit(number % 10, left, color, canvas);
148 }
149 
drawDash(int left,SkCanvas & canvas)150 void RefreshRateOverlay::drawDash(int left, SkCanvas& canvas) {
151     left += kDigitWidth + kDigitSpace;
152     SegmentDrawer::drawSegment(SegmentDrawer::Segment::Middle, left, SK_ColorRED, canvas);
153 
154     left += kDigitWidth + kDigitSpace;
155     SegmentDrawer::drawSegment(SegmentDrawer::Segment::Middle, left, SK_ColorRED, canvas);
156 }
157 
create(FpsRange range,ftl::Flags<Features> features)158 std::unique_ptr<RefreshRateOverlay> RefreshRateOverlay::create(FpsRange range,
159                                                                ftl::Flags<Features> features) {
160     std::unique_ptr<RefreshRateOverlay> overlay =
161             std::make_unique<RefreshRateOverlay>(ConstructorTag{}, range, features);
162     if (overlay->initCheck()) {
163         return overlay;
164     }
165 
166     ALOGE("%s: Failed to create RefreshRateOverlay", __func__);
167     return {};
168 }
169 
RefreshRateOverlay(ConstructorTag,FpsRange fpsRange,ftl::Flags<Features> features)170 RefreshRateOverlay::RefreshRateOverlay(ConstructorTag, FpsRange fpsRange,
171                                        ftl::Flags<Features> features)
172       : mFpsRange(fpsRange),
173         mFeatures(features),
174         mSurfaceControl(
175                 SurfaceControlHolder::createSurfaceControlHolder(String8("RefreshRateOverlay"))) {
176     if (!mSurfaceControl) {
177         ALOGE("%s: Failed to create buffer state layer", __func__);
178         return;
179     }
180 
181     createTransaction()
182             .setLayer(mSurfaceControl->get(), INT32_MAX - 2)
183             .setTrustedOverlay(mSurfaceControl->get(), true)
184             .apply();
185 }
186 
initCheck() const187 bool RefreshRateOverlay::initCheck() const {
188     return mSurfaceControl != nullptr;
189 }
190 
getOrCreateBuffers(Fps refreshRate,Fps renderFps,bool idle)191 auto RefreshRateOverlay::getOrCreateBuffers(Fps refreshRate, Fps renderFps, bool idle)
192         -> const Buffers& {
193     static const Buffers kNoBuffers;
194     if (!mSurfaceControl) return kNoBuffers;
195 
196     // avoid caching different render rates if RenderRate is anyway not visible
197     if (!mFeatures.test(Features::RenderRate)) {
198         renderFps = 0_Hz;
199     }
200 
201     const auto transformHint =
202             static_cast<ui::Transform::RotationFlags>(mSurfaceControl->get()->getTransformHint());
203 
204     // Tell SurfaceFlinger about the pre-rotation on the buffer.
205     const auto transform = [&] {
206         switch (transformHint) {
207             case ui::Transform::ROT_90:
208                 return ui::Transform::ROT_270;
209             case ui::Transform::ROT_270:
210                 return ui::Transform::ROT_90;
211             default:
212                 return ui::Transform::ROT_0;
213         }
214     }();
215 
216     createTransaction().setTransform(mSurfaceControl->get(), transform).apply();
217 
218     BufferCache::const_iterator it = mBufferCache.find(
219             {refreshRate.getIntValue(), renderFps.getIntValue(), transformHint, idle});
220     if (it == mBufferCache.end()) {
221         const int maxFps = mFpsRange.max.getIntValue();
222 
223         // Clamp to supported refresh rate range: the current refresh rate may be outside of this
224         // range if the display has changed its set of supported refresh rates.
225         const int refreshIntFps = std::clamp(refreshRate.getIntValue(), 0, maxFps);
226         const int renderIntFps = renderFps.getIntValue();
227         const float fpsScale = static_cast<float>(refreshIntFps) / maxFps;
228 
229         constexpr SkColor kMinFpsColor = SK_ColorRED;
230         constexpr SkColor kMaxFpsColor = SK_ColorGREEN;
231         constexpr float kAlpha = 0.8f;
232 
233         SkColor4f colorBase = SkColor4f::FromColor(kMaxFpsColor) * fpsScale;
234         const SkColor4f minFpsColor = SkColor4f::FromColor(kMinFpsColor) * (1 - fpsScale);
235 
236         colorBase.fR = colorBase.fR + minFpsColor.fR;
237         colorBase.fG = colorBase.fG + minFpsColor.fG;
238         colorBase.fB = colorBase.fB + minFpsColor.fB;
239         colorBase.fA = kAlpha;
240 
241         const SkColor color = colorBase.toSkColor();
242 
243         auto buffers = draw(refreshIntFps, renderIntFps, idle, color, transformHint, mFeatures);
244         it = mBufferCache
245                      .try_emplace({refreshIntFps, renderIntFps, transformHint, idle},
246                      std::move(buffers)).first;
247     }
248 
249     return it->second;
250 }
251 
setViewport(ui::Size viewport)252 void RefreshRateOverlay::setViewport(ui::Size viewport) {
253     constexpr int32_t kMaxWidth = 1000;
254     const auto width = std::min({kMaxWidth, viewport.width, viewport.height});
255     const auto height = 2 * width;
256     Rect frame((5 * width) >> 4, height >> 5);
257 
258     if (!mFeatures.test(Features::ShowInMiddle)) {
259         frame.offsetBy(width >> 5, height >> 4);
260     } else {
261         frame.offsetBy(width >> 1, height >> 4);
262     }
263 
264     createTransaction()
265             .setMatrix(mSurfaceControl->get(), frame.getWidth() / static_cast<float>(kBufferWidth),
266                        0, 0, frame.getHeight() / static_cast<float>(kBufferHeight))
267             .setPosition(mSurfaceControl->get(), frame.left, frame.top)
268             .apply();
269 }
270 
setLayerStack(ui::LayerStack stack)271 void RefreshRateOverlay::setLayerStack(ui::LayerStack stack) {
272     createTransaction().setLayerStack(mSurfaceControl->get(), stack).apply();
273 }
274 
changeRefreshRate(Fps refreshRate,Fps renderFps)275 void RefreshRateOverlay::changeRefreshRate(Fps refreshRate, Fps renderFps) {
276     mRefreshRate = refreshRate;
277     mRenderFps = renderFps;
278     const auto buffer = getOrCreateBuffers(refreshRate, renderFps, mIsVrrIdle)[mFrame];
279     createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
280 }
281 
onVrrIdle(bool idle)282 void RefreshRateOverlay::onVrrIdle(bool idle) {
283     mIsVrrIdle = idle;
284     if (!mRefreshRate || !mRenderFps) return;
285 
286     const auto buffer = getOrCreateBuffers(*mRefreshRate, *mRenderFps, mIsVrrIdle)[mFrame];
287     createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
288 }
289 
changeRenderRate(Fps renderFps)290 void RefreshRateOverlay::changeRenderRate(Fps renderFps) {
291     if (mFeatures.test(Features::RenderRate) && mRefreshRate &&
292         FlagManager::getInstance().misc1()) {
293         mRenderFps = renderFps;
294         const auto buffer = getOrCreateBuffers(*mRefreshRate, renderFps, mIsVrrIdle)[mFrame];
295         createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
296     }
297 }
298 
animate()299 void RefreshRateOverlay::animate() {
300     if (!mFeatures.test(Features::Spinner) || !mRefreshRate) return;
301 
302     const auto& buffers = getOrCreateBuffers(*mRefreshRate, *mRenderFps, mIsVrrIdle);
303     mFrame = (mFrame + 1) % buffers.size();
304     const auto buffer = buffers[mFrame];
305     createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
306 }
307 
createTransaction() const308 SurfaceComposerClient::Transaction RefreshRateOverlay::createTransaction() const {
309     constexpr float kFrameRate = 0.f;
310     constexpr int8_t kCompatibility = ANATIVEWINDOW_FRAME_RATE_NO_VOTE;
311     constexpr int8_t kSeamlessness = ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS;
312 
313     const sp<SurfaceControl>& surface = mSurfaceControl->get();
314 
315     SurfaceComposerClient::Transaction transaction;
316     if (isSetByHwc()) {
317         transaction.setFlags(surface, layer_state_t::eLayerIsRefreshRateIndicator,
318                              layer_state_t::eLayerIsRefreshRateIndicator);
319         // Disable overlay layer caching when refresh rate is updated by the HWC.
320         transaction.setCachingHint(surface, gui::CachingHint::Disabled);
321     }
322     transaction.setFrameRate(surface, kFrameRate, kCompatibility, kSeamlessness);
323     return transaction;
324 }
325 
326 } // namespace android
327