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