blob: 35f12a0484315ce14beea11be43cf18bcf7174ed [file] [log] [blame]
Ady Abraham03b02dd2019-03-21 15:40:11 -07001/*
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
Marin Shalamanovf7f6b3c2020-12-09 13:19:38 +010017#include <algorithm>
18
Alec Mouri9b133ca2023-11-14 19:00:01 +000019#include <common/FlagManager.h>
Ady Abraham03b02dd2019-03-21 15:40:11 -070020#include "Client.h"
21#include "Layer.h"
Ady Abraham3649ea82022-07-08 16:04:02 -070022#include "RefreshRateOverlay.h"
Ady Abraham03b02dd2019-03-21 15:40:11 -070023
rnlee756005b2021-05-27 10:46:36 -070024#include <SkSurface.h>
Ady Abraham2cb8b622019-12-02 18:55:33 -080025
26#undef LOG_TAG
27#define LOG_TAG "RefreshRateOverlay"
28
Ady Abraham03b02dd2019-03-21 15:40:11 -070029namespace android {
30
Ady Abrahame2946322024-07-10 17:45:29 -070031auto RefreshRateOverlay::draw(int refreshRate, int renderFps, bool idle, SkColor color,
Sally Qi147581b2023-06-27 11:55:34 -070032 ui::Transform::RotationFlags rotation, ftl::Flags<Features> features)
33 -> Buffers {
Ady Abraham0aa373a2022-11-22 13:56:50 -080034 const size_t loopCount = features.test(Features::Spinner) ? 6 : 1;
Ady Abrahame2946322024-07-10 17:45:29 -070035 const bool isSetByHwc = features.test(Features::SetByHwc);
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070036
37 Buffers buffers;
38 buffers.reserve(loopCount);
39
40 for (size_t i = 0; i < loopCount; i++) {
rnlee756005b2021-05-27 10:46:36 -070041 // Pre-rotate the buffer before it reaches SurfaceFlinger.
42 SkMatrix canvasTransform = SkMatrix();
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070043 const auto [bufferWidth, bufferHeight] = [&]() -> std::pair<int, int> {
rnlee756005b2021-05-27 10:46:36 -070044 switch (rotation) {
45 case ui::Transform::ROT_90:
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070046 canvasTransform.setTranslate(kBufferHeight, 0);
47 canvasTransform.preRotate(90.f);
48 return {kBufferHeight, kBufferWidth};
rnlee756005b2021-05-27 10:46:36 -070049 case ui::Transform::ROT_270:
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070050 canvasTransform.setRotate(270.f, kBufferWidth / 2.f, kBufferWidth / 2.f);
51 return {kBufferHeight, kBufferWidth};
rnlee756005b2021-05-27 10:46:36 -070052 default:
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070053 return {kBufferWidth, kBufferHeight};
rnlee756005b2021-05-27 10:46:36 -070054 }
55 }();
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070056
Ady Abrahamd11bade2022-08-01 16:18:03 -070057 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");
Dominik Laskowski8c4356c2022-03-21 08:19:54 -070064
Alec Mouri7013b6f2021-02-12 11:16:54 -080065 const status_t bufferStatus = buffer->initCheck();
66 LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "RefreshRateOverlay: Buffer failed to allocate: %d",
67 bufferStatus);
rnlee756005b2021-05-27 10:46:36 -070068
Kevin Lubick00bec722023-05-12 19:26:03 +000069 sk_sp<SkSurface> surface = SkSurfaces::Raster(
70 SkImageInfo::MakeN32Premul(bufferWidth, bufferHeight));
rnlee756005b2021-05-27 10:46:36 -070071 SkCanvas* canvas = surface->getCanvas();
72 canvas->setMatrix(canvasTransform);
73
Ady Abraham29d0da32020-07-16 18:39:33 -070074 int left = 0;
Ady Abrahame2946322024-07-10 17:45:29 -070075 if (idle && !isSetByHwc) {
76 drawDash(left, *canvas);
77 } else {
78 drawNumber(refreshRate, left, color, *canvas);
79 }
Ady Abraham0aa373a2022-11-22 13:56:50 -080080 left += 3 * (kDigitWidth + kDigitSpace);
81 if (features.test(Features::Spinner)) {
Ady Abraham29d0da32020-07-16 18:39:33 -070082 switch (i) {
83 case 0:
Sally Qi147581b2023-06-27 11:55:34 -070084 SegmentDrawer::drawSegment(SegmentDrawer::Segment::Upper, left, color, *canvas);
Ady Abraham29d0da32020-07-16 18:39:33 -070085 break;
86 case 1:
Sally Qi147581b2023-06-27 11:55:34 -070087 SegmentDrawer::drawSegment(SegmentDrawer::Segment::UpperRight, left, color,
88 *canvas);
Ady Abraham29d0da32020-07-16 18:39:33 -070089 break;
90 case 2:
Sally Qi147581b2023-06-27 11:55:34 -070091 SegmentDrawer::drawSegment(SegmentDrawer::Segment::LowerRight, left, color,
92 *canvas);
Ady Abraham29d0da32020-07-16 18:39:33 -070093 break;
94 case 3:
Sally Qi147581b2023-06-27 11:55:34 -070095 SegmentDrawer::drawSegment(SegmentDrawer::Segment::Bottom, left, color,
96 *canvas);
Ady Abraham29d0da32020-07-16 18:39:33 -070097 break;
98 case 4:
Sally Qi147581b2023-06-27 11:55:34 -070099 SegmentDrawer::drawSegment(SegmentDrawer::Segment::LowerLeft, left, color,
100 *canvas);
Ady Abraham29d0da32020-07-16 18:39:33 -0700101 break;
102 case 5:
Sally Qi147581b2023-06-27 11:55:34 -0700103 SegmentDrawer::drawSegment(SegmentDrawer::Segment::UpperLeft, left, color,
104 *canvas);
Ady Abraham29d0da32020-07-16 18:39:33 -0700105 break;
106 }
107 }
108
Ady Abraham0aa373a2022-11-22 13:56:50 -0800109 left += kDigitWidth + kDigitSpace;
110
111 if (features.test(Features::RenderRate)) {
Ady Abrahame2946322024-07-10 17:45:29 -0700112 if (idle) {
113 drawDash(left, *canvas);
114 } else {
115 drawNumber(renderFps, left, color, *canvas);
116 }
Ady Abraham0aa373a2022-11-22 13:56:50 -0800117 }
118 left += 3 * (kDigitWidth + kDigitSpace);
119
rnlee756005b2021-05-27 10:46:36 -0700120 void* pixels = nullptr;
121 buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700122
rnlee756005b2021-05-27 10:46:36 -0700123 const SkImageInfo& imageInfo = surface->imageInfo();
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700124 const size_t dstRowBytes =
125 buffer->getStride() * static_cast<size_t>(imageInfo.bytesPerPixel());
126
rnlee756005b2021-05-27 10:46:36 -0700127 canvas->readPixels(imageInfo, pixels, dstRowBytes, 0, 0);
Ady Abraham29d0da32020-07-16 18:39:33 -0700128 buffer->unlock();
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700129 buffers.push_back(std::move(buffer));
Ady Abraham29d0da32020-07-16 18:39:33 -0700130 }
131 return buffers;
Ady Abraham2cb8b622019-12-02 18:55:33 -0800132}
133
Sally Qi147581b2023-06-27 11:55:34 -0700134void RefreshRateOverlay::drawNumber(int number, int left, SkColor color, SkCanvas& canvas) {
Ady Abraham0aa373a2022-11-22 13:56:50 -0800135 if (number < 0 || number >= 1000) return;
136
137 if (number >= 100) {
Sally Qi147581b2023-06-27 11:55:34 -0700138 SegmentDrawer::drawDigit(number / 100, left, color, canvas);
Ady Abraham0aa373a2022-11-22 13:56:50 -0800139 }
140 left += kDigitWidth + kDigitSpace;
141
142 if (number >= 10) {
Sally Qi147581b2023-06-27 11:55:34 -0700143 SegmentDrawer::drawDigit((number / 10) % 10, left, color, canvas);
Ady Abraham0aa373a2022-11-22 13:56:50 -0800144 }
145 left += kDigitWidth + kDigitSpace;
146
Sally Qi147581b2023-06-27 11:55:34 -0700147 SegmentDrawer::drawDigit(number % 10, left, color, canvas);
Ady Abraham3649ea82022-07-08 16:04:02 -0700148}
149
Ady Abrahame2946322024-07-10 17:45:29 -0700150void 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
Ady Abrahamddba9342023-10-02 16:28:03 -0700158std::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
170RefreshRateOverlay::RefreshRateOverlay(ConstructorTag, FpsRange fpsRange,
171 ftl::Flags<Features> features)
Sally Qi147581b2023-06-27 11:55:34 -0700172 : mFpsRange(fpsRange),
173 mFeatures(features),
174 mSurfaceControl(
175 SurfaceControlHolder::createSurfaceControlHolder(String8("RefreshRateOverlay"))) {
chaviw70aa7572021-09-22 12:27:57 -0500176 if (!mSurfaceControl) {
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700177 ALOGE("%s: Failed to create buffer state layer", __func__);
178 return;
Ady Abraham03b02dd2019-03-21 15:40:11 -0700179 }
180
ramindanib2158ee2023-02-13 20:29:59 -0800181 createTransaction()
Ady Abraham3649ea82022-07-08 16:04:02 -0700182 .setLayer(mSurfaceControl->get(), INT32_MAX - 2)
183 .setTrustedOverlay(mSurfaceControl->get(), true)
Ady Abraham78c4a242021-11-30 17:49:44 -0800184 .apply();
Ady Abraham03b02dd2019-03-21 15:40:11 -0700185}
186
Ady Abrahamddba9342023-10-02 16:28:03 -0700187bool RefreshRateOverlay::initCheck() const {
188 return mSurfaceControl != nullptr;
189}
190
Ady Abrahame2946322024-07-10 17:45:29 -0700191auto RefreshRateOverlay::getOrCreateBuffers(Fps refreshRate, Fps renderFps, bool idle)
192 -> const Buffers& {
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700193 static const Buffers kNoBuffers;
194 if (!mSurfaceControl) return kNoBuffers;
195
Ady Abraham0aa373a2022-11-22 13:56:50 -0800196 // avoid caching different render rates if RenderRate is anyway not visible
197 if (!mFeatures.test(Features::RenderRate)) {
198 renderFps = 0_Hz;
199 }
200
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700201 const auto transformHint =
Ady Abraham3649ea82022-07-08 16:04:02 -0700202 static_cast<ui::Transform::RotationFlags>(mSurfaceControl->get()->getTransformHint());
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700203
rnlee756005b2021-05-27 10:46:36 -0700204 // 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 }();
chaviw70aa7572021-09-22 12:27:57 -0500215
ramindanib2158ee2023-02-13 20:29:59 -0800216 createTransaction().setTransform(mSurfaceControl->get(), transform).apply();
rnlee756005b2021-05-27 10:46:36 -0700217
Ady Abrahame2946322024-07-10 17:45:29 -0700218 BufferCache::const_iterator it = mBufferCache.find(
219 {refreshRate.getIntValue(), renderFps.getIntValue(), transformHint, idle});
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700220 if (it == mBufferCache.end()) {
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700221 const int maxFps = mFpsRange.max.getIntValue();
222
ramindanic6e522e2024-05-07 16:42:51 -0700223 // 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);
Ady Abraham0aa373a2022-11-22 13:56:50 -0800226 const int renderIntFps = renderFps.getIntValue();
ramindanic6e522e2024-05-07 16:42:51 -0700227 const float fpsScale = static_cast<float>(refreshIntFps) / maxFps;
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700228
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
Ady Abrahame2946322024-07-10 17:45:29 -0700243 auto buffers = draw(refreshIntFps, renderIntFps, idle, color, transformHint, mFeatures);
Ady Abraham0aa373a2022-11-22 13:56:50 -0800244 it = mBufferCache
Ady Abrahame2946322024-07-10 17:45:29 -0700245 .try_emplace({refreshIntFps, renderIntFps, transformHint, idle},
246 std::move(buffers)).first;
Ady Abraham2cb8b622019-12-02 18:55:33 -0800247 }
Marin Shalamanovf7f6b3c2020-12-09 13:19:38 +0100248
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700249 return it->second;
Ady Abraham2cb8b622019-12-02 18:55:33 -0800250}
251
Dominik Laskowski20134642020-04-20 22:36:44 -0700252void RefreshRateOverlay::setViewport(ui::Size viewport) {
Ady Abrahamcba8d6c2021-06-03 18:05:04 -0700253 constexpr int32_t kMaxWidth = 1000;
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700254 const auto width = std::min({kMaxWidth, viewport.width, viewport.height});
Ady Abrahamcba8d6c2021-06-03 18:05:04 -0700255 const auto height = 2 * width;
Ady Abraham0aa373a2022-11-22 13:56:50 -0800256 Rect frame((5 * width) >> 4, height >> 5);
Yifei Zhangcfb7bb32023-01-12 16:17:14 -0800257
258 if (!mFeatures.test(Features::ShowInMiddle)) {
259 frame.offsetBy(width >> 5, height >> 4);
260 } else {
261 frame.offsetBy(width >> 1, height >> 4);
262 }
Ady Abraham2cb8b622019-12-02 18:55:33 -0800263
ramindanib2158ee2023-02-13 20:29:59 -0800264 createTransaction()
Ady Abraham3649ea82022-07-08 16:04:02 -0700265 .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)
Dominik Laskowski1f6fc702022-03-21 08:34:50 -0700268 .apply();
Ady Abraham03b02dd2019-03-21 15:40:11 -0700269}
270
Dominik Laskowski29fa1462021-04-27 15:51:50 -0700271void RefreshRateOverlay::setLayerStack(ui::LayerStack stack) {
ramindanib2158ee2023-02-13 20:29:59 -0800272 createTransaction().setLayerStack(mSurfaceControl->get(), stack).apply();
Ady Abraham1b11bc62021-06-03 19:51:19 -0700273}
274
Ying Wei22d59cc2024-05-11 02:41:08 +0000275void RefreshRateOverlay::changeRefreshRate(Fps refreshRate, Fps renderFps) {
276 mRefreshRate = refreshRate;
Ady Abraham0aa373a2022-11-22 13:56:50 -0800277 mRenderFps = renderFps;
Ady Abrahame2946322024-07-10 17:45:29 -0700278 const auto buffer = getOrCreateBuffers(refreshRate, renderFps, mIsVrrIdle)[mFrame];
279 createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
280}
281
282void RefreshRateOverlay::onVrrIdle(bool idle) {
283 mIsVrrIdle = idle;
284 if (!mRefreshRate || !mRenderFps) return;
285
286 const auto buffer = getOrCreateBuffers(*mRefreshRate, *mRenderFps, mIsVrrIdle)[mFrame];
ramindanib2158ee2023-02-13 20:29:59 -0800287 createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
Ady Abraham29d0da32020-07-16 18:39:33 -0700288}
289
ramindani3faf5742023-09-21 13:45:12 -0700290void RefreshRateOverlay::changeRenderRate(Fps renderFps) {
Ying Wei22d59cc2024-05-11 02:41:08 +0000291 if (mFeatures.test(Features::RenderRate) && mRefreshRate &&
292 FlagManager::getInstance().misc1()) {
ramindani3faf5742023-09-21 13:45:12 -0700293 mRenderFps = renderFps;
Ady Abrahame2946322024-07-10 17:45:29 -0700294 const auto buffer = getOrCreateBuffers(*mRefreshRate, renderFps, mIsVrrIdle)[mFrame];
ramindani3faf5742023-09-21 13:45:12 -0700295 createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
296 }
297}
298
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700299void RefreshRateOverlay::animate() {
Ying Wei22d59cc2024-05-11 02:41:08 +0000300 if (!mFeatures.test(Features::Spinner) || !mRefreshRate) return;
Ady Abraham29d0da32020-07-16 18:39:33 -0700301
Ady Abrahame2946322024-07-10 17:45:29 -0700302 const auto& buffers = getOrCreateBuffers(*mRefreshRate, *mRenderFps, mIsVrrIdle);
Ady Abraham29d0da32020-07-16 18:39:33 -0700303 mFrame = (mFrame + 1) % buffers.size();
Dominik Laskowski8c4356c2022-03-21 08:19:54 -0700304 const auto buffer = buffers[mFrame];
ramindanib2158ee2023-02-13 20:29:59 -0800305 createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply();
306}
307
308SurfaceComposerClient::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);
ramindania3816ab2023-04-25 18:41:16 -0700319 // Disable overlay layer caching when refresh rate is updated by the HWC.
320 transaction.setCachingHint(surface, gui::CachingHint::Disabled);
ramindanib2158ee2023-02-13 20:29:59 -0800321 }
322 transaction.setFrameRate(surface, kFrameRate, kCompatibility, kSeamlessness);
323 return transaction;
Dominik Laskowski20134642020-04-20 22:36:44 -0700324}
325
326} // namespace android