blob: 6598bd861b22240b8a254f4f1df4470b92cc301d [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
17#include "RefreshRateOverlay.h"
18#include "Client.h"
19#include "Layer.h"
20
Ady Abraham2cb8b622019-12-02 18:55:33 -080021#include <gui/IProducerListener.h>
22
23#undef LOG_TAG
24#define LOG_TAG "RefreshRateOverlay"
25
Ady Abraham03b02dd2019-03-21 15:40:11 -070026namespace android {
27
Ady Abraham2cb8b622019-12-02 18:55:33 -080028void RefreshRateOverlay::SevenSegmentDrawer::drawRect(const Rect& r, const half4& color,
29 const sp<GraphicBuffer>& buffer,
30 uint8_t* pixels) {
31 for (int32_t j = r.top; j < r.bottom; j++) {
32 if (j >= buffer->getHeight()) {
33 break;
34 }
35
36 for (int32_t i = r.left; i < r.right; i++) {
37 if (i >= buffer->getWidth()) {
38 break;
39 }
40
41 uint8_t* iter = pixels + 4 * (i + (buffer->getStride() * j));
42 iter[0] = uint8_t(color.r * 255);
43 iter[1] = uint8_t(color.g * 255);
44 iter[2] = uint8_t(color.b * 255);
45 iter[3] = uint8_t(color.a * 255);
46 }
47 }
48}
49
50void RefreshRateOverlay::SevenSegmentDrawer::drawSegment(Segment segment, int left,
51 const half4& color,
52 const sp<GraphicBuffer>& buffer,
53 uint8_t* pixels) {
54 const Rect rect = [&]() {
55 switch (segment) {
56 case Segment::Upper:
57 return Rect(left, 0, left + DIGIT_WIDTH, DIGIT_SPACE);
58 case Segment::UpperLeft:
59 return Rect(left, 0, left + DIGIT_SPACE, DIGIT_HEIGHT / 2);
60 case Segment::UpperRight:
61 return Rect(left + DIGIT_WIDTH - DIGIT_SPACE, 0, left + DIGIT_WIDTH,
62 DIGIT_HEIGHT / 2);
63 case Segment::Middle:
64 return Rect(left, DIGIT_HEIGHT / 2 - DIGIT_SPACE / 2, left + DIGIT_WIDTH,
65 DIGIT_HEIGHT / 2 + DIGIT_SPACE / 2);
66 case Segment::LowerLeft:
67 return Rect(left, DIGIT_HEIGHT / 2, left + DIGIT_SPACE, DIGIT_HEIGHT);
68 case Segment::LowerRight:
69 return Rect(left + DIGIT_WIDTH - DIGIT_SPACE, DIGIT_HEIGHT / 2, left + DIGIT_WIDTH,
70 DIGIT_HEIGHT);
71 case Segment::Buttom:
72 return Rect(left, DIGIT_HEIGHT - DIGIT_SPACE, left + DIGIT_WIDTH, DIGIT_HEIGHT);
73 }
74 }();
75
76 drawRect(rect, color, buffer, pixels);
77}
78
79void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, const half4& color,
80 const sp<GraphicBuffer>& buffer,
81 uint8_t* pixels) {
82 if (digit < 0 || digit > 9) return;
83
84 if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 7 ||
85 digit == 8 || digit == 9)
86 drawSegment(Segment::Upper, left, color, buffer, pixels);
87 if (digit == 0 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || digit == 9)
88 drawSegment(Segment::UpperLeft, left, color, buffer, pixels);
89 if (digit == 0 || digit == 1 || digit == 2 || digit == 3 || digit == 4 || digit == 7 ||
90 digit == 8 || digit == 9)
91 drawSegment(Segment::UpperRight, left, color, buffer, pixels);
92 if (digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || digit == 8 ||
93 digit == 9)
94 drawSegment(Segment::Middle, left, color, buffer, pixels);
95 if (digit == 0 || digit == 2 || digit == 6 || digit == 8)
96 drawSegment(Segment::LowerLeft, left, color, buffer, pixels);
97 if (digit == 0 || digit == 1 || digit == 3 || digit == 4 || digit == 5 || digit == 6 ||
98 digit == 7 || digit == 8 || digit == 9)
99 drawSegment(Segment::LowerRight, left, color, buffer, pixels);
100 if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 8 ||
101 digit == 9)
102 drawSegment(Segment::Buttom, left, color, buffer, pixels);
103}
104
105sp<GraphicBuffer> RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number,
106 const half4& color) {
107 if (number < 0 || number > 1000) return nullptr;
108
109 const auto hundreds = number / 100;
110 const auto tens = (number / 10) % 10;
111 const auto ones = number % 10;
112
113 sp<GraphicBuffer> buffer =
114 new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1,
115 GRALLOC_USAGE_SW_WRITE_RARELY, "RefreshRateOverlayBuffer");
116 uint8_t* pixels;
117 buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
118 int left = 0;
119 if (hundreds != 0) {
120 drawDigit(hundreds, left, color, buffer, pixels);
121 left += DIGIT_WIDTH + DIGIT_SPACE;
122 }
123
124 if (tens != 0) {
125 drawDigit(tens, left, color, buffer, pixels);
126 left += DIGIT_WIDTH + DIGIT_SPACE;
127 }
128
129 drawDigit(ones, left, color, buffer, pixels);
130 buffer->unlock();
131 return buffer;
132}
133
Ady Abraham03b02dd2019-03-21 15:40:11 -0700134RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger)
135 : mFlinger(flinger), mClient(new Client(&mFlinger)) {
136 createLayer();
Ady Abraham2cb8b622019-12-02 18:55:33 -0800137 primeCache();
Ady Abraham03b02dd2019-03-21 15:40:11 -0700138}
139
140bool RefreshRateOverlay::createLayer() {
141 const status_t ret =
Ady Abraham2cb8b622019-12-02 18:55:33 -0800142 mFlinger.createLayer(String8("RefreshRateOverlay"), mClient,
143 SevenSegmentDrawer::getWidth(), SevenSegmentDrawer::getHeight(),
144 PIXEL_FORMAT_RGBA_8888,
145 ISurfaceComposerClient::eFXSurfaceBufferState, LayerMetadata(),
146 &mIBinder, &mGbp, nullptr);
Ady Abraham03b02dd2019-03-21 15:40:11 -0700147 if (ret) {
Ady Abraham2cb8b622019-12-02 18:55:33 -0800148 ALOGE("failed to create buffer state layer");
Ady Abraham03b02dd2019-03-21 15:40:11 -0700149 return false;
150 }
151
Ady Abrahamfed164b2019-05-10 17:12:54 -0700152 Mutex::Autolock _l(mFlinger.mStateLock);
Ady Abraham03b02dd2019-03-21 15:40:11 -0700153 mLayer = mClient->getLayerUser(mIBinder);
Ady Abrahamfed164b2019-05-10 17:12:54 -0700154
155 // setting Layer's Z requires resorting layersSortedByZ
156 ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer);
157 if (mLayer->setLayer(INT32_MAX - 2) && idx >= 0) {
158 mFlinger.mCurrentState.layersSortedByZ.removeAt(idx);
159 mFlinger.mCurrentState.layersSortedByZ.add(mLayer);
160 }
Ady Abraham03b02dd2019-03-21 15:40:11 -0700161
162 return true;
163}
164
Ady Abraham2cb8b622019-12-02 18:55:33 -0800165void RefreshRateOverlay::primeCache() {
166 auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
167 if (allRefreshRates.size() == 1) {
168 auto fps = allRefreshRates.begin()->second.fps;
169 half4 color = {LOW_FPS_COLOR, ALPHA};
170 mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
171 return;
172 }
173
174 std::vector<uint32_t> supportedFps;
175 supportedFps.reserve(allRefreshRates.size());
176 for (auto [ignored, refreshRate] : allRefreshRates) {
177 supportedFps.push_back(refreshRate.fps);
178 }
179
180 std::sort(supportedFps.begin(), supportedFps.end());
181 const auto mLowFps = supportedFps[0];
182 const auto mHighFps = supportedFps[supportedFps.size() - 1];
183 for (auto fps : supportedFps) {
184 const auto fpsScale = float(fps - mLowFps) / (mHighFps - mLowFps);
185 half4 color;
186 color.r = HIGH_FPS_COLOR.r * fpsScale + LOW_FPS_COLOR.r * (1 - fpsScale);
187 color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale);
188 color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale);
189 color.a = ALPHA;
190 mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
191 }
192}
193
Ady Abraham2139f732019-11-13 18:56:40 -0800194void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
Ady Abraham2cb8b622019-12-02 18:55:33 -0800195 auto buffer = mBufferCache[refreshRate.fps];
196 mLayer->setBuffer(buffer, 0, 0, {});
197 mLayer->setFrame(Rect(20, 120, 20 + SevenSegmentDrawer::getWidth(),
198 120 + SevenSegmentDrawer::getHeight()));
199
Ady Abrahamfe57b762019-04-17 20:06:14 -0700200 mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
Ady Abraham03b02dd2019-03-21 15:40:11 -0700201}
202
203}; // namespace android