xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Utils/OverlayUtils.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /**
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
18*38e8c45fSAndroid Build Coastguard Worker #pragma once
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker #include "BackgroundExecutor.h"
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
23*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion"
24*38e8c45fSAndroid Build Coastguard Worker #include <SkCanvas.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <SkPaint.h>
26*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceComposerClient.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <utils/StrongPointer.h>
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker namespace android {
32*38e8c45fSAndroid Build Coastguard Worker 
33*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kDigitWidth = 64;
34*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kDigitHeight = 100;
35*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kDigitSpace = 16;
36*38e8c45fSAndroid Build Coastguard Worker 
37*38e8c45fSAndroid Build Coastguard Worker // HdrSdrRatioOverlay re-uses this value though it doesn't really need such amount buffer.
38*38e8c45fSAndroid Build Coastguard Worker // for output good-looking and code conciseness.
39*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kMaxDigits = /*displayFps*/ 3 + /*renderFps*/ 3 + /*spinner*/ 1;
40*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kBufferWidth = kMaxDigits * kDigitWidth + (kMaxDigits - 1) * kDigitSpace;
41*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kBufferHeight = kDigitHeight;
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker class SurfaceControl;
44*38e8c45fSAndroid Build Coastguard Worker 
45*38e8c45fSAndroid Build Coastguard Worker // Helper class to delete the SurfaceControl on a helper thread as
46*38e8c45fSAndroid Build Coastguard Worker // SurfaceControl assumes its destruction happens without SurfaceFlinger::mStateLock held.
47*38e8c45fSAndroid Build Coastguard Worker class SurfaceControlHolder {
48*38e8c45fSAndroid Build Coastguard Worker public:
SurfaceControlHolder(sp<SurfaceControl> sc)49*38e8c45fSAndroid Build Coastguard Worker     explicit SurfaceControlHolder(sp<SurfaceControl> sc) : mSurfaceControl(std::move(sc)){};
50*38e8c45fSAndroid Build Coastguard Worker 
~SurfaceControlHolder()51*38e8c45fSAndroid Build Coastguard Worker     ~SurfaceControlHolder() {
52*38e8c45fSAndroid Build Coastguard Worker         // Hand the sp<SurfaceControl> to the helper thread to release the last
53*38e8c45fSAndroid Build Coastguard Worker         // reference. This makes sure that the SurfaceControl is destructed without
54*38e8c45fSAndroid Build Coastguard Worker         // SurfaceFlinger::mStateLock held.
55*38e8c45fSAndroid Build Coastguard Worker         BackgroundExecutor::getInstance().sendCallbacks(
56*38e8c45fSAndroid Build Coastguard Worker                 {[sc = std::move(mSurfaceControl)]() mutable { sc.clear(); }});
57*38e8c45fSAndroid Build Coastguard Worker     }
58*38e8c45fSAndroid Build Coastguard Worker 
createSurfaceControlHolder(const String8 & name)59*38e8c45fSAndroid Build Coastguard Worker     static std::unique_ptr<SurfaceControlHolder> createSurfaceControlHolder(const String8& name) {
60*38e8c45fSAndroid Build Coastguard Worker         sp<SurfaceControl> surfaceControl =
61*38e8c45fSAndroid Build Coastguard Worker                 SurfaceComposerClient::getDefault()
62*38e8c45fSAndroid Build Coastguard Worker                         ->createSurface(name, kBufferWidth, kBufferHeight, PIXEL_FORMAT_RGBA_8888,
63*38e8c45fSAndroid Build Coastguard Worker                                         ISurfaceComposerClient::eFXSurfaceBufferState);
64*38e8c45fSAndroid Build Coastguard Worker         return std::make_unique<SurfaceControlHolder>(std::move(surfaceControl));
65*38e8c45fSAndroid Build Coastguard Worker     }
66*38e8c45fSAndroid Build Coastguard Worker 
get()67*38e8c45fSAndroid Build Coastguard Worker     const sp<SurfaceControl>& get() const { return mSurfaceControl; }
68*38e8c45fSAndroid Build Coastguard Worker 
69*38e8c45fSAndroid Build Coastguard Worker private:
70*38e8c45fSAndroid Build Coastguard Worker     sp<SurfaceControl> mSurfaceControl;
71*38e8c45fSAndroid Build Coastguard Worker };
72*38e8c45fSAndroid Build Coastguard Worker 
73*38e8c45fSAndroid Build Coastguard Worker // Helper class to draw digit and decimal point.
74*38e8c45fSAndroid Build Coastguard Worker class SegmentDrawer {
75*38e8c45fSAndroid Build Coastguard Worker public:
76*38e8c45fSAndroid Build Coastguard Worker     enum class Segment {
77*38e8c45fSAndroid Build Coastguard Worker         Upper,
78*38e8c45fSAndroid Build Coastguard Worker         UpperLeft,
79*38e8c45fSAndroid Build Coastguard Worker         UpperRight,
80*38e8c45fSAndroid Build Coastguard Worker         Middle,
81*38e8c45fSAndroid Build Coastguard Worker         LowerLeft,
82*38e8c45fSAndroid Build Coastguard Worker         LowerRight,
83*38e8c45fSAndroid Build Coastguard Worker         Bottom,
84*38e8c45fSAndroid Build Coastguard Worker         DecimalPoint
85*38e8c45fSAndroid Build Coastguard Worker     };
drawSegment(Segment segment,int left,SkColor color,SkCanvas & canvas)86*38e8c45fSAndroid Build Coastguard Worker     static void drawSegment(Segment segment, int left, SkColor color, SkCanvas& canvas) {
87*38e8c45fSAndroid Build Coastguard Worker         const SkRect rect = [&]() {
88*38e8c45fSAndroid Build Coastguard Worker             switch (segment) {
89*38e8c45fSAndroid Build Coastguard Worker                 case Segment::Upper:
90*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left, 0, left + kDigitWidth, kDigitSpace);
91*38e8c45fSAndroid Build Coastguard Worker                 case Segment::UpperLeft:
92*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left, 0, left + kDigitSpace, kDigitHeight / 2.);
93*38e8c45fSAndroid Build Coastguard Worker                 case Segment::UpperRight:
94*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left + kDigitWidth - kDigitSpace, 0, left + kDigitWidth,
95*38e8c45fSAndroid Build Coastguard Worker                                             kDigitHeight / 2.);
96*38e8c45fSAndroid Build Coastguard Worker                 case Segment::Middle:
97*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left, kDigitHeight / 2. - kDigitSpace / 2.,
98*38e8c45fSAndroid Build Coastguard Worker                                             left + kDigitWidth,
99*38e8c45fSAndroid Build Coastguard Worker                                             kDigitHeight / 2. + kDigitSpace / 2.);
100*38e8c45fSAndroid Build Coastguard Worker                 case Segment::LowerLeft:
101*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left, kDigitHeight / 2., left + kDigitSpace,
102*38e8c45fSAndroid Build Coastguard Worker                                             kDigitHeight);
103*38e8c45fSAndroid Build Coastguard Worker                 case Segment::LowerRight:
104*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left + kDigitWidth - kDigitSpace, kDigitHeight / 2.,
105*38e8c45fSAndroid Build Coastguard Worker                                             left + kDigitWidth, kDigitHeight);
106*38e8c45fSAndroid Build Coastguard Worker                 case Segment::Bottom:
107*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left, kDigitHeight - kDigitSpace, left + kDigitWidth,
108*38e8c45fSAndroid Build Coastguard Worker                                             kDigitHeight);
109*38e8c45fSAndroid Build Coastguard Worker                 case Segment::DecimalPoint:
110*38e8c45fSAndroid Build Coastguard Worker                     return SkRect::MakeLTRB(left, kDigitHeight - kDigitSpace, left + kDigitSpace,
111*38e8c45fSAndroid Build Coastguard Worker                                             kDigitHeight);
112*38e8c45fSAndroid Build Coastguard Worker             }
113*38e8c45fSAndroid Build Coastguard Worker         }();
114*38e8c45fSAndroid Build Coastguard Worker 
115*38e8c45fSAndroid Build Coastguard Worker         SkPaint paint;
116*38e8c45fSAndroid Build Coastguard Worker         paint.setColor(color);
117*38e8c45fSAndroid Build Coastguard Worker         paint.setBlendMode(SkBlendMode::kSrc);
118*38e8c45fSAndroid Build Coastguard Worker         canvas.drawRect(rect, paint);
119*38e8c45fSAndroid Build Coastguard Worker     }
120*38e8c45fSAndroid Build Coastguard Worker 
drawDigit(int digit,int left,SkColor color,SkCanvas & canvas)121*38e8c45fSAndroid Build Coastguard Worker     static void drawDigit(int digit, int left, SkColor color, SkCanvas& canvas) {
122*38e8c45fSAndroid Build Coastguard Worker         if (digit < 0 || digit > 9) return;
123*38e8c45fSAndroid Build Coastguard Worker 
124*38e8c45fSAndroid Build Coastguard Worker         if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 7 ||
125*38e8c45fSAndroid Build Coastguard Worker             digit == 8 || digit == 9)
126*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::Upper, left, color, canvas);
127*38e8c45fSAndroid Build Coastguard Worker         if (digit == 0 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || digit == 9)
128*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::UpperLeft, left, color, canvas);
129*38e8c45fSAndroid Build Coastguard Worker         if (digit == 0 || digit == 1 || digit == 2 || digit == 3 || digit == 4 || digit == 7 ||
130*38e8c45fSAndroid Build Coastguard Worker             digit == 8 || digit == 9)
131*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::UpperRight, left, color, canvas);
132*38e8c45fSAndroid Build Coastguard Worker         if (digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || digit == 8 ||
133*38e8c45fSAndroid Build Coastguard Worker             digit == 9)
134*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::Middle, left, color, canvas);
135*38e8c45fSAndroid Build Coastguard Worker         if (digit == 0 || digit == 2 || digit == 6 || digit == 8)
136*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::LowerLeft, left, color, canvas);
137*38e8c45fSAndroid Build Coastguard Worker         if (digit == 0 || digit == 1 || digit == 3 || digit == 4 || digit == 5 || digit == 6 ||
138*38e8c45fSAndroid Build Coastguard Worker             digit == 7 || digit == 8 || digit == 9)
139*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::LowerRight, left, color, canvas);
140*38e8c45fSAndroid Build Coastguard Worker         if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 8 ||
141*38e8c45fSAndroid Build Coastguard Worker             digit == 9)
142*38e8c45fSAndroid Build Coastguard Worker             drawSegment(Segment::Bottom, left, color, canvas);
143*38e8c45fSAndroid Build Coastguard Worker     }
144*38e8c45fSAndroid Build Coastguard Worker };
145*38e8c45fSAndroid Build Coastguard Worker 
146*38e8c45fSAndroid Build Coastguard Worker } // namespace android
147